Merge "Add dynamic keyspace creation"
[sdc.git] / openecomp-be / lib / openecomp-sdc-enrichment-lib / openecomp-sdc-enrichment-impl / src / main / java / org / openecomp / sdc / enrichment / impl / tosca / PortMirroringEnricher.java
1 package org.openecomp.sdc.enrichment.impl.tosca;
2
3 import static org.openecomp.sdc.tosca.services.DataModelUtil.getClonedObject;
4 import static org.openecomp.sdc.tosca.services.ToscaConstants.PORT_MIRRORING_CAPABILITY_CP_PROPERTY_NAME;
5 import static org.openecomp.sdc.tosca.services.ToscaConstants.PORT_MIRRORING_CAPABILITY_ID;
6
7 import org.apache.commons.collections4.CollectionUtils;
8 import org.apache.commons.collections4.MapUtils;
9 import org.openecomp.sdc.datatypes.error.ErrorMessage;
10 import org.openecomp.sdc.enrichment.impl.tosca.model.PortMirroringConnectionPointDescription;
11 import org.openecomp.sdc.logging.context.impl.MdcDataDebugMessage;
12 import org.openecomp.sdc.tosca.datatypes.ToscaNodeType;
13 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
14 import org.openecomp.sdc.tosca.datatypes.model.CapabilityAssignment;
15 import org.openecomp.sdc.tosca.datatypes.model.Import;
16 import org.openecomp.sdc.tosca.datatypes.model.NodeTemplate;
17 import org.openecomp.sdc.tosca.datatypes.model.PropertyDefinition;
18 import org.openecomp.sdc.tosca.datatypes.model.RequirementAssignment;
19 import org.openecomp.sdc.tosca.datatypes.model.ServiceTemplate;
20 import org.openecomp.sdc.tosca.services.DataModelUtil;
21 import org.openecomp.sdc.tosca.services.ToscaConstants;
22 import org.openecomp.sdc.tosca.services.ToscaUtil;
23 import org.openecomp.sdc.translator.services.heattotosca.HeatToToscaUtil;
24 import org.openecomp.sdc.translator.services.heattotosca.globaltypes.GlobalTypesGenerator;
25
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.LinkedList;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Objects;
32 import java.util.Optional;
33 import java.util.stream.Collectors;
34
35 public class PortMirroringEnricher {
36   //Map of service template file name and map of all port node template ids, node template
37   private Map<String, Map<String, NodeTemplate>> portNodeTemplates = new HashMap<>();
38   //Map of service template file name and map of external port node template ids, node template
39   private Map<String, Map<String, NodeTemplate>> externalPortNodeTemplates = new HashMap<>();
40   //Map of substitution service template name and the list of ports with link requirement from
41   // the abstract
42   private Map<String, List<String>> portNodeTemplateIdsFromAbstract = new HashMap<>();
43   private static MdcDataDebugMessage mdcDataDebugMessage = new MdcDataDebugMessage();
44   private Map<String, ServiceTemplate> globalTypesServiceTemplate =
45       GlobalTypesGenerator.getGlobalTypesServiceTemplate();
46
47   /**
48    * Enrich tosca for port mirroring.
49    *
50    * @param toscaServiceModel the tosca service model
51    * @return the map          Error descriptor map
52    */
53   public Map<String, List<ErrorMessage>> enrich(ToscaServiceModel toscaServiceModel) {
54     mdcDataDebugMessage.debugEntryMessage(null);
55     Map<String, List<ErrorMessage>> errors = new HashMap<>();
56     Map<String, ServiceTemplate> serviceTemplates = toscaServiceModel.getServiceTemplates();
57     serviceTemplates.entrySet().stream()
58         //Skipping the service templates which do not contain topology template
59         .filter(serviceTemplateEntry -> serviceTemplateEntry.getValue()
60             .getTopology_template() != null)
61         .forEach(serviceTemplateEntry ->
62             //Collect all the ports across all the service templates
63             collectPorts(serviceTemplateEntry.getValue()));
64     //Collect External ports from the list of all ports collected above
65     filterExternalPorts(toscaServiceModel);
66     //Handle external port changes
67     handleExternalPorts(toscaServiceModel);
68     mdcDataDebugMessage.debugExitMessage(null);
69     return errors;
70   }
71
72   private void collectPorts(ServiceTemplate serviceTemplate) {
73     Map<String, NodeTemplate> nodeTemplates =
74         serviceTemplate.getTopology_template().getNode_templates();
75     if (Objects.nonNull(nodeTemplates)) {
76       //Get all concrete port node templates from the service template
77       Map<String, NodeTemplate> serviceTemplatePortNodeTemplates = nodeTemplates.entrySet().stream()
78           .filter(nodeTemplateEntry -> (Objects.nonNull(nodeTemplateEntry.getValue()))
79               && (isPortNodeTemplate(nodeTemplateEntry.getValue().getType())))
80           .collect(Collectors.toMap(nodeTemplateEntry -> nodeTemplateEntry.getKey(),
81               nodeTemplateEntry -> nodeTemplateEntry.getValue()));
82
83       portNodeTemplates.put(ToscaUtil.getServiceTemplateFileName(serviceTemplate),
84           serviceTemplatePortNodeTemplates);
85
86       //Get all linked internal ports from abstract node template link requirements
87       List<String> abstractLinkedPortNodeTemplates = new ArrayList<>();
88       for (Map.Entry<String, NodeTemplate> nodeTemplateEntry : nodeTemplates.entrySet()) {
89         NodeTemplate nodeTemplate = nodeTemplateEntry.getValue();
90         if (isSubstitutableNodeTemplate(nodeTemplate)) {
91           List<Map<String, RequirementAssignment>> requirements = nodeTemplate.getRequirements();
92           if (Objects.nonNull(requirements)) {
93             for (Map<String, RequirementAssignment> requirement : requirements) {
94               String requirementId = requirement.keySet().iterator().next();
95               String abstractLinkRequirementIdPrefix = ToscaConstants.LINK_REQUIREMENT_ID + "_";
96               if (requirementId.startsWith(abstractLinkRequirementIdPrefix)) {
97                 //Collect port node template ids from the link requirement ids in the abstract
98                 // node template
99                 abstractLinkedPortNodeTemplates.add(requirementId.substring(requirementId
100                     .indexOf("_") + 1));
101               }
102             }
103           }
104           if (CollectionUtils.isNotEmpty(abstractLinkedPortNodeTemplates)) {
105             //Populate a map of the substitution service templates and list of internal ports
106             addCollectedPortsToAbstractServiceTemplatePortMap(nodeTemplate,
107                 abstractLinkedPortNodeTemplates);
108           }
109         }
110       }
111     }
112   }
113
114   private void addCollectedPortsToAbstractServiceTemplatePortMap(NodeTemplate nodeTemplate,
115                                                                  List<String>
116                                                                      abstractLinkedPortNodeTemplates) {
117     String substitutionServiceTemplateName = null;
118     if (nodeTemplate.getProperties() != null) {
119       Map serviceTemplateFilter = (Map<String, Object>) nodeTemplate.getProperties()
120           .get(ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME);
121       substitutionServiceTemplateName = (String)
122           serviceTemplateFilter.get(ToscaConstants.SUBSTITUTE_SERVICE_TEMPLATE_PROPERTY_NAME);
123       if (Objects.nonNull(substitutionServiceTemplateName)) {
124         if (portNodeTemplateIdsFromAbstract.containsKey(substitutionServiceTemplateName)) {
125           List<String> portList =
126               portNodeTemplateIdsFromAbstract.get(substitutionServiceTemplateName);
127           portList.addAll(abstractLinkedPortNodeTemplates);
128           portNodeTemplateIdsFromAbstract.put(substitutionServiceTemplateName, portList);
129         } else {
130           portNodeTemplateIdsFromAbstract.put(substitutionServiceTemplateName,
131               abstractLinkedPortNodeTemplates);
132         }
133       }
134     }
135   }
136
137   private void filterExternalPorts(ToscaServiceModel toscaServiceModel) {
138     for (Map.Entry<String, Map<String, NodeTemplate>> portNodeTemplateEntry : portNodeTemplates
139         .entrySet()) {
140       Map<String, NodeTemplate> externalPorts = new HashMap<>();
141       String serviceTemplateFileName = portNodeTemplateEntry.getKey();
142       Map<String, NodeTemplate> portNodeTemplateMap = portNodeTemplateEntry.getValue();
143       for (Map.Entry<String, NodeTemplate> portNodeTemplate : portNodeTemplateMap.entrySet()) {
144         String nodeTemplateId = portNodeTemplate.getKey();
145         NodeTemplate nodeTemplate = portNodeTemplate.getValue();
146         String newPortNodeType = nodeTemplate.getType();
147         if (!isInternalPort(serviceTemplateFileName, nodeTemplateId, nodeTemplate)) {
148           //External Port
149           externalPorts.putIfAbsent(nodeTemplateId, nodeTemplate);
150         }
151       }
152       externalPortNodeTemplates.putIfAbsent(serviceTemplateFileName, externalPorts);
153     }
154   }
155
156   private void updateExternalPortNodeTemplate(NodeTemplate externalPortNodeTemplate,
157                                               ToscaServiceModel toscaServiceModel) {
158     String currentPortNodeType = externalPortNodeTemplate.getType();
159     if (currentPortNodeType.equals(ToscaNodeType.CONTRAIL_PORT)
160         || currentPortNodeType.equals(ToscaNodeType.CONTRAILV2_VIRTUAL_MACHINE_INTERFACE)) {
161       //Set external contrail port node type
162       externalPortNodeTemplate.setType(ToscaNodeType.EXTERNAL_CONTRAIL_PORT);
163       addPortMirroringCapability(externalPortNodeTemplate);
164     } else if (currentPortNodeType.equals(ToscaNodeType.NEUTRON_PORT)) {
165       //Set external neutron port node type
166       externalPortNodeTemplate.setType(ToscaNodeType.EXTERNAL_NEUTRON_PORT);
167       addPortMirroringCapability(externalPortNodeTemplate);
168     }
169   }
170
171   private void handleExternalPorts(ToscaServiceModel toscaServiceModel) {
172
173     for (Map.Entry<String, Map<String, NodeTemplate>> entry : externalPortNodeTemplates
174         .entrySet()) {
175       String serviceTemplateName = entry.getKey();
176       ServiceTemplate serviceTemplate =
177           toscaServiceModel.getServiceTemplates().get(serviceTemplateName);
178       Map<String, NodeTemplate> externalNodeTemplates = entry.getValue();
179       if (MapUtils.isNotEmpty(externalNodeTemplates)) {
180         for (Map.Entry<String, NodeTemplate> externalNodeTemplate : externalNodeTemplates
181             .entrySet()) {
182           String externalPortNodeTemplateId = externalNodeTemplate.getKey();
183           updateExternalPortNodeTemplate(externalNodeTemplate.getValue(), toscaServiceModel);
184           if (serviceTemplate.getTopology_template().getSubstitution_mappings() != null) {
185             //Add port mirroring capability to substitution mapping for external ports
186             addPortMirroringSubstitutionMappingCapability(serviceTemplate,
187                 externalPortNodeTemplateId);
188           }
189           handleExternalPortProperties(externalNodeTemplate.getValue());
190         }
191         addGlobalTypeImport(serviceTemplate);
192       }
193     }
194   }
195
196   private void handleExternalPortProperties(NodeTemplate portNodeTemplate) {
197
198     ServiceTemplate serviceTemplate = globalTypesServiceTemplate.get("openecomp/nodes.yml");
199     String externalPortType = portNodeTemplate.getType();
200     Map<String, PropertyDefinition> globalTypesportProperties = new HashMap<>();
201     globalTypesportProperties.putAll(
202         serviceTemplate.getNode_types().get("org.openecomp.resource.cp.nodes.network.Port")
203             .getProperties());
204     globalTypesportProperties
205         .putAll(serviceTemplate.getNode_types().get(externalPortType).getProperties());
206
207     Map<String, Object> properties = portNodeTemplate.getProperties();
208     Map<String, Object> filteredProperties = new HashMap<>();
209
210     if (MapUtils.isEmpty(properties)) {
211       return;
212     }
213
214     for (Map.Entry<String, Object> propertyEntry : properties.entrySet()) {
215       if (globalTypesportProperties.containsKey(propertyEntry.getKey())) {
216         filteredProperties.put(propertyEntry.getKey(), propertyEntry.getValue());
217       }
218     }
219
220     if (!MapUtils.isEmpty(filteredProperties)) {
221       portNodeTemplate.setProperties(filteredProperties);
222     } else {
223       portNodeTemplate.setProperties(null);
224     }
225
226   }
227
228   private void addPortMirroringSubstitutionMappingCapability(ServiceTemplate serviceTemplate,
229                                                              String externalPortNodeTemplateId) {
230     List<String> portMirroringCapability = new LinkedList<>();
231     portMirroringCapability.add(externalPortNodeTemplateId);
232     portMirroringCapability.add(PORT_MIRRORING_CAPABILITY_ID);
233     String substitutionMappingCapabilityId = PORT_MIRRORING_CAPABILITY_ID + "_"
234         + externalPortNodeTemplateId;
235     DataModelUtil.addSubstitutionMappingCapability(serviceTemplate,
236         substitutionMappingCapabilityId, portMirroringCapability);
237   }
238
239   private void addPortMirroringCapability(NodeTemplate portNodeTemplate) {
240     List<Map<String, CapabilityAssignment>> capabilities = portNodeTemplate.getCapabilities();
241     if (Objects.isNull(capabilities)) {
242       capabilities = new ArrayList<>();
243     }
244     Map<String, Object> portMirroringCapabilityProperties = new HashMap<>();
245     PortMirroringConnectionPointDescription connectionPoint = new
246         PortMirroringConnectionPointDescription();
247     //Get Network role property
248     if (Objects.nonNull(portNodeTemplate.getProperties())) {
249       Object networkRolePropertyValue =
250           portNodeTemplate.getProperties().get(ToscaConstants.PORT_NETWORK_ROLE_PROPERTY_NAME);
251       if (Objects.nonNull(networkRolePropertyValue)) {
252         Object portMirroringNetworkRolePropertyVal = getClonedObject(networkRolePropertyValue);
253         connectionPoint.setNetwork_role(portMirroringNetworkRolePropertyVal);
254       }
255     }
256     //Get NFC_Type from the binding requirement node
257     if (Objects.nonNull(portNodeTemplate.getRequirements())) {
258       Optional<List<RequirementAssignment>> requirementAssignment =
259           DataModelUtil.getRequirementAssignment(portNodeTemplate.getRequirements(), ToscaConstants
260               .BINDING_REQUIREMENT_ID);
261       if (requirementAssignment.isPresent()) {
262         RequirementAssignment bindingRequirementAssignment = requirementAssignment.get().get(0);
263         String node = bindingRequirementAssignment.getNode();
264         connectionPoint.setNfc_type(node);
265       }
266     }
267
268     if (!connectionPoint.isEmpty()) {
269       portMirroringCapabilityProperties.put(PORT_MIRRORING_CAPABILITY_CP_PROPERTY_NAME,
270           connectionPoint);
271       DataModelUtil.addNodeTemplateCapability(portNodeTemplate,
272           PORT_MIRRORING_CAPABILITY_ID, portMirroringCapabilityProperties, null);
273     }
274   }
275
276   private void addGlobalTypeImport(ServiceTemplate serviceTemplate) {
277     List<Map<String, Import>> imports = serviceTemplate.getImports();
278     Map<String, Import> openecompIndexImport = new HashMap<>();
279     openecompIndexImport.put("openecomp_index",
280         HeatToToscaUtil.createServiceTemplateImport(globalTypesServiceTemplate
281             .get("openecomp/_index.yml")));
282     imports.add(openecompIndexImport);
283   }
284
285   private boolean isPortNodeTemplate(String nodeType) {
286     //Check if node corresponds to a concrete port node
287     if (Objects.nonNull(nodeType)) {
288       if (nodeType.equals(ToscaNodeType.NEUTRON_PORT)
289           || nodeType.equals(ToscaNodeType.CONTRAILV2_VIRTUAL_MACHINE_INTERFACE)
290           || nodeType.equals(ToscaNodeType.CONTRAIL_PORT)) {
291         return true;
292       }
293     }
294     return false;
295   }
296
297   private boolean isSubstitutableNodeTemplate(NodeTemplate nodeTemplate) {
298     if (Objects.nonNull(nodeTemplate.getDirectives())) {
299       return nodeTemplate.getDirectives().contains(ToscaConstants
300           .NODE_TEMPLATE_DIRECTIVE_SUBSTITUTABLE);
301     }
302     return false;
303   }
304
305   private boolean isInternalPort(String serviceTemplateFileName, String nodeTemplateId,
306                                  NodeTemplate nodeTemplate) {
307     return isAbstractInternalPort(serviceTemplateFileName, nodeTemplateId)
308         || isConcreteInternalPort(nodeTemplate);
309   }
310
311   private boolean isAbstractInternalPort(String serviceTemplateFileName, String nodeTemplateId) {
312     //Check if port corresponds to an abstract internal port
313     if (portNodeTemplateIdsFromAbstract.containsKey(serviceTemplateFileName)) {
314       return portNodeTemplateIdsFromAbstract.get(serviceTemplateFileName).contains(nodeTemplateId);
315     }
316     return false;
317   }
318
319
320   private boolean isConcreteInternalPort(NodeTemplate nodeTemplate) {
321     //Check if node template contains a link requirement
322     List<Map<String, RequirementAssignment>> requirements = nodeTemplate.getRequirements();
323     if (Objects.nonNull(requirements)) {
324       for (Map<String, RequirementAssignment> requirement : requirements) {
325         String requirementId = requirement.keySet().iterator().next();
326         if (requirementId.equals(ToscaConstants.LINK_REQUIREMENT_ID)) {
327           return true;
328         }
329       }
330     }
331     return false;
332   }
333 }