2 * Copyright © 2016-2017 European Support Limited
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package org.openecomp.sdc.enrichment.impl.tosca;
19 import org.apache.commons.collections4.CollectionUtils;
20 import org.apache.commons.collections4.MapUtils;
21 import org.openecomp.core.utilities.orchestration.OnboardingTypesEnum;
22 import org.openecomp.sdc.datatypes.error.ErrorMessage;
23 import org.openecomp.sdc.enrichment.impl.tosca.model.PortMirroringConnectionPointDescription;
24 import org.openecomp.sdc.logging.context.impl.MdcDataDebugMessage;
25 import org.openecomp.sdc.tosca.datatypes.ToscaElementTypes;
26 import org.openecomp.sdc.tosca.datatypes.ToscaNodeType;
27 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
28 import org.openecomp.sdc.tosca.datatypes.model.CapabilityAssignment;
29 import org.openecomp.sdc.tosca.datatypes.model.Import;
30 import org.openecomp.sdc.tosca.datatypes.model.NodeTemplate;
31 import org.openecomp.sdc.tosca.datatypes.model.NodeType;
32 import org.openecomp.sdc.tosca.datatypes.model.PropertyDefinition;
33 import org.openecomp.sdc.tosca.datatypes.model.RequirementAssignment;
34 import org.openecomp.sdc.tosca.datatypes.model.ServiceTemplate;
35 import org.openecomp.sdc.tosca.services.DataModelUtil;
36 import org.openecomp.sdc.tosca.services.ToscaAnalyzerService;
37 import org.openecomp.sdc.tosca.services.ToscaConstants;
38 import org.openecomp.sdc.tosca.services.ToscaUtil;
39 import org.openecomp.sdc.tosca.services.impl.ToscaAnalyzerServiceImpl;
40 import org.openecomp.sdc.translator.services.heattotosca.HeatToToscaUtil;
41 import org.openecomp.sdc.translator.services.heattotosca.globaltypes.GlobalTypesGenerator;
43 import java.util.ArrayList;
44 import java.util.Arrays;
45 import java.util.HashMap;
46 import java.util.HashSet;
47 import java.util.LinkedList;
48 import java.util.List;
50 import java.util.Objects;
51 import java.util.Optional;
53 import java.util.stream.Collectors;
55 import static org.openecomp.sdc.tosca.services.DataModelUtil.getClonedObject;
56 import static org.openecomp.sdc.tosca.services.ToscaConstants.PORT_MIRRORING_CAPABILITY_CP_PROPERTY_NAME;
57 import static org.openecomp.sdc.tosca.services.ToscaConstants.PORT_MIRRORING_CAPABILITY_ID;
59 public class PortMirroringEnricher {
60 //Map of service template file name and map of all port node template ids, node template
61 private Map<String, Map<String, NodeTemplate>> portNodeTemplates = new HashMap<>();
62 //Map of service template file name and map of external port node template ids, node template
63 private Map<String, Map<String, NodeTemplate>> externalPortNodeTemplates = new HashMap<>();
64 //Map of substitution service template name and the list of ports with link requirement from
66 private Map<String, List<String>> portNodeTemplateIdsFromAbstract = new HashMap<>();
67 private static MdcDataDebugMessage mdcDataDebugMessage = new MdcDataDebugMessage();
68 private Map<String, ServiceTemplate> globalTypesServiceTemplate =
69 GlobalTypesGenerator.getGlobalTypesServiceTemplate(OnboardingTypesEnum.ZIP);
72 * Enrich tosca for port mirroring.
74 * @param toscaServiceModel the tosca service model
75 * @return the map Error descriptor map
77 public Map<String, List<ErrorMessage>> enrich(ToscaServiceModel toscaServiceModel) {
78 mdcDataDebugMessage.debugEntryMessage(null);
79 Map<String, List<ErrorMessage>> errors = new HashMap<>();
80 Map<String, ServiceTemplate> serviceTemplates = toscaServiceModel.getServiceTemplates();
81 serviceTemplates.entrySet().stream()
82 //Skipping the service templates which do not contain topology template
83 .filter(serviceTemplateEntry -> serviceTemplateEntry.getValue()
84 .getTopology_template() != null)
85 .forEach(serviceTemplateEntry ->
86 //Collect all the ports across all the service templates
87 collectPorts(serviceTemplateEntry.getValue()));
88 //Collect External ports from the list of all ports collected above
89 filterExternalPorts(toscaServiceModel);
90 //Handle external port changes
91 handleExternalPorts(toscaServiceModel);
92 mdcDataDebugMessage.debugExitMessage(null);
96 private void collectPorts(ServiceTemplate serviceTemplate) {
97 Map<String, NodeTemplate> nodeTemplates =
98 serviceTemplate.getTopology_template().getNode_templates();
99 if (Objects.nonNull(nodeTemplates)) {
100 //Get all concrete port node templates from the service template
101 Map<String, NodeTemplate> serviceTemplatePortNodeTemplates = nodeTemplates.entrySet().stream()
102 .filter(nodeTemplateEntry -> (Objects.nonNull(nodeTemplateEntry.getValue()))
103 && (isPortNodeTemplate(nodeTemplateEntry.getValue().getType())))
104 .collect(Collectors.toMap(nodeTemplateEntry -> nodeTemplateEntry.getKey(),
105 nodeTemplateEntry -> nodeTemplateEntry.getValue()));
107 portNodeTemplates.put(ToscaUtil.getServiceTemplateFileName(serviceTemplate),
108 serviceTemplatePortNodeTemplates);
110 //Get all linked internal ports from abstract node template link requirements
111 List<String> abstractLinkedPortNodeTemplates = new ArrayList<>();
112 for (Map.Entry<String, NodeTemplate> nodeTemplateEntry : nodeTemplates.entrySet()) {
113 NodeTemplate nodeTemplate = nodeTemplateEntry.getValue();
114 if (isSubstitutableNodeTemplate(nodeTemplate)) {
115 List<Map<String, RequirementAssignment>> requirements = nodeTemplate.getRequirements();
116 if (Objects.nonNull(requirements)) {
117 for (Map<String, RequirementAssignment> requirement : requirements) {
118 String requirementId = requirement.keySet().iterator().next();
119 String abstractLinkRequirementIdPrefix = ToscaConstants.LINK_REQUIREMENT_ID + "_";
120 if (requirementId.startsWith(abstractLinkRequirementIdPrefix)) {
121 //Collect port node template ids from the link requirement ids in the abstract
123 abstractLinkedPortNodeTemplates.add(requirementId.substring(requirementId
128 if (CollectionUtils.isNotEmpty(abstractLinkedPortNodeTemplates)) {
129 //Populate a map of the substitution service templates and list of internal ports
130 addCollectedPortsToAbstractServiceTemplatePortMap(nodeTemplate,
131 abstractLinkedPortNodeTemplates);
138 private void addCollectedPortsToAbstractServiceTemplatePortMap(NodeTemplate nodeTemplate,
140 abstractLinkedPortNodeTemplates) {
141 String substitutionServiceTemplateName = null;
142 if (nodeTemplate.getProperties() != null) {
143 Map serviceTemplateFilter = (Map<String, Object>) nodeTemplate.getProperties()
144 .get(ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME);
145 substitutionServiceTemplateName = (String)
146 serviceTemplateFilter.get(ToscaConstants.SUBSTITUTE_SERVICE_TEMPLATE_PROPERTY_NAME);
147 if (Objects.nonNull(substitutionServiceTemplateName)) {
148 if (portNodeTemplateIdsFromAbstract.containsKey(substitutionServiceTemplateName)) {
149 List<String> portList =
150 portNodeTemplateIdsFromAbstract.get(substitutionServiceTemplateName);
151 portList.addAll(abstractLinkedPortNodeTemplates);
152 portNodeTemplateIdsFromAbstract.put(substitutionServiceTemplateName, portList);
154 portNodeTemplateIdsFromAbstract.put(substitutionServiceTemplateName,
155 abstractLinkedPortNodeTemplates);
161 private void filterExternalPorts(ToscaServiceModel toscaServiceModel) {
162 for (Map.Entry<String, Map<String, NodeTemplate>> portNodeTemplateEntry : portNodeTemplates
164 Map<String, NodeTemplate> externalPorts = new HashMap<>();
165 String serviceTemplateFileName = portNodeTemplateEntry.getKey();
166 Map<String, NodeTemplate> portNodeTemplateMap = portNodeTemplateEntry.getValue();
167 for (Map.Entry<String, NodeTemplate> portNodeTemplate : portNodeTemplateMap.entrySet()) {
168 String nodeTemplateId = portNodeTemplate.getKey();
169 NodeTemplate nodeTemplate = portNodeTemplate.getValue();
170 String newPortNodeType = nodeTemplate.getType();
171 if (!isInternalPort(serviceTemplateFileName, nodeTemplateId, nodeTemplate)) {
173 externalPorts.putIfAbsent(nodeTemplateId, nodeTemplate);
176 externalPortNodeTemplates.putIfAbsent(serviceTemplateFileName, externalPorts);
180 private void updateExternalPortNodeTemplate(NodeTemplate externalPortNodeTemplate,
181 ToscaServiceModel toscaServiceModel) {
182 String currentPortNodeType = externalPortNodeTemplate.getType();
183 if (currentPortNodeType.equals(ToscaNodeType.CONTRAIL_PORT)
184 || currentPortNodeType.equals(ToscaNodeType.CONTRAILV2_VIRTUAL_MACHINE_INTERFACE)) {
185 //Set external contrail port node type
186 externalPortNodeTemplate.setType(ToscaNodeType.EXTERNAL_CONTRAIL_PORT);
187 addPortMirroringCapability(externalPortNodeTemplate);
188 } else if (currentPortNodeType.equals(ToscaNodeType.NEUTRON_PORT)) {
189 //Set external neutron port node type
190 externalPortNodeTemplate.setType(ToscaNodeType.EXTERNAL_NEUTRON_PORT);
191 addPortMirroringCapability(externalPortNodeTemplate);
195 private void handleExternalPorts(ToscaServiceModel toscaServiceModel) {
197 for (Map.Entry<String, Map<String, NodeTemplate>> entry : externalPortNodeTemplates
199 String serviceTemplateName = entry.getKey();
200 ServiceTemplate serviceTemplate =
201 toscaServiceModel.getServiceTemplates().get(serviceTemplateName);
202 Map<String, NodeTemplate> externalNodeTemplates = entry.getValue();
203 if (MapUtils.isNotEmpty(externalNodeTemplates)) {
204 for (Map.Entry<String, NodeTemplate> externalNodeTemplate : externalNodeTemplates
206 String externalPortNodeTemplateId = externalNodeTemplate.getKey();
207 updateExternalPortNodeTemplate(externalNodeTemplate.getValue(), toscaServiceModel);
208 if (serviceTemplate.getTopology_template().getSubstitution_mappings() != null) {
209 //Add port mirroring capability to substitution mapping for external ports
210 addPortMirroringSubstitutionMappingCapability(serviceTemplate,
211 externalPortNodeTemplateId);
213 handleExternalPortProperties(externalNodeTemplate.getValue(), serviceTemplate, toscaServiceModel);
215 addGlobalTypeImport(serviceTemplate);
220 private void handleExternalPortProperties(NodeTemplate portNodeTemplate,
221 ServiceTemplate serviceTemplate,
222 ToscaServiceModel toscaServiceModel){
224 ToscaAnalyzerService toscaAnalyzerService = new ToscaAnalyzerServiceImpl();
225 String externalPortType = portNodeTemplate.getType();
226 Map<String, PropertyDefinition> globalTypesportProperties = new HashMap<>();
227 NodeType flatNodeType =
228 (NodeType) toscaAnalyzerService.getFlatEntity(ToscaElementTypes.NODE_TYPE, externalPortType, serviceTemplate, toscaServiceModel);
229 globalTypesportProperties.putAll(flatNodeType.getProperties());
231 Map<String, Object> properties = portNodeTemplate.getProperties();
232 Map<String, Object> filteredProperties = new HashMap<>();
234 if(MapUtils.isEmpty(properties)){
238 for(Map.Entry<String, Object> propertyEntry: properties.entrySet()){
239 if(globalTypesportProperties.containsKey(propertyEntry.getKey())){
240 filteredProperties.put(propertyEntry.getKey(), propertyEntry.getValue());
244 if(!MapUtils.isEmpty(filteredProperties)) {
245 portNodeTemplate.setProperties(filteredProperties);
247 portNodeTemplate.setProperties(null);
252 private void addPortMirroringSubstitutionMappingCapability(ServiceTemplate serviceTemplate,
253 String externalPortNodeTemplateId) {
254 List<String> portMirroringCapability = new LinkedList<>();
255 portMirroringCapability.add(externalPortNodeTemplateId);
256 portMirroringCapability.add(PORT_MIRRORING_CAPABILITY_ID);
257 String substitutionMappingCapabilityId = PORT_MIRRORING_CAPABILITY_ID + "_"
258 + externalPortNodeTemplateId;
259 DataModelUtil.addSubstitutionMappingCapability(serviceTemplate,
260 substitutionMappingCapabilityId, portMirroringCapability);
263 private void addPortMirroringCapability(NodeTemplate portNodeTemplate) {
264 List<Map<String, CapabilityAssignment>> capabilities = portNodeTemplate.getCapabilities();
265 if (Objects.isNull(capabilities)) {
266 capabilities = new ArrayList<>();
268 Map<String, Object> portMirroringCapabilityProperties = new HashMap<>();
269 PortMirroringConnectionPointDescription connectionPoint = new
270 PortMirroringConnectionPointDescription();
271 //Get Network role property
272 if (Objects.nonNull(portNodeTemplate.getProperties())) {
273 Object networkRolePropertyValue =
274 portNodeTemplate.getProperties().get(ToscaConstants.PORT_NETWORK_ROLE_PROPERTY_NAME);
275 if (Objects.nonNull(networkRolePropertyValue)) {
276 Object portMirroringNetworkRolePropertyVal = getClonedObject(networkRolePropertyValue);
277 connectionPoint.setNetwork_role(portMirroringNetworkRolePropertyVal);
280 //Get NFC_Type from the binding requirement node
281 if (Objects.nonNull(portNodeTemplate.getRequirements())) {
282 Optional<List<RequirementAssignment>> requirementAssignment =
283 DataModelUtil.getRequirementAssignment(portNodeTemplate.getRequirements(), ToscaConstants
284 .BINDING_REQUIREMENT_ID);
285 if (requirementAssignment.isPresent()) {
286 RequirementAssignment bindingRequirementAssignment = requirementAssignment.get().get(0);
287 String node = bindingRequirementAssignment.getNode();
288 connectionPoint.setNfc_type(node);
292 if (!connectionPoint.isEmpty()) {
293 portMirroringCapabilityProperties.put(PORT_MIRRORING_CAPABILITY_CP_PROPERTY_NAME,
295 DataModelUtil.addNodeTemplateCapability(portNodeTemplate,
296 PORT_MIRRORING_CAPABILITY_ID, portMirroringCapabilityProperties, null);
300 private void addGlobalTypeImport(ServiceTemplate serviceTemplate) {
301 List<Map<String, Import>> imports = serviceTemplate.getImports();
302 Map<String, Import> openecompIndexImport = new HashMap<>();
303 openecompIndexImport.put("openecomp_index",
304 HeatToToscaUtil.createServiceTemplateImport(globalTypesServiceTemplate
305 .get("openecomp/_index.yml")));
306 imports.add(openecompIndexImport);
309 private boolean isPortNodeTemplate(String nodeType) {
310 //Check if node corresponds to a concrete port node
311 Set<String> portNodeTypes = getPortNodeTypes();
312 return Objects.nonNull(nodeType)
313 && portNodeTypes.contains(nodeType);
316 private Set<String> getPortNodeTypes(){
317 return new HashSet<>(Arrays.asList(ToscaNodeType.NEUTRON_PORT,
318 ToscaNodeType.CONTRAILV2_VIRTUAL_MACHINE_INTERFACE,
319 ToscaNodeType.CONTRAIL_PORT));
322 private boolean isSubstitutableNodeTemplate(NodeTemplate nodeTemplate) {
323 if (Objects.nonNull(nodeTemplate.getDirectives())) {
324 return nodeTemplate.getDirectives().contains(ToscaConstants
325 .NODE_TEMPLATE_DIRECTIVE_SUBSTITUTABLE);
330 private boolean isInternalPort(String serviceTemplateFileName, String nodeTemplateId,
331 NodeTemplate nodeTemplate) {
332 return isAbstractInternalPort(serviceTemplateFileName, nodeTemplateId)
333 || isConcreteInternalPort(nodeTemplate);
336 private boolean isAbstractInternalPort(String serviceTemplateFileName, String nodeTemplateId) {
337 //Check if port corresponds to an abstract internal port
338 if (portNodeTemplateIdsFromAbstract.containsKey(serviceTemplateFileName)) {
339 return portNodeTemplateIdsFromAbstract.get(serviceTemplateFileName).contains(nodeTemplateId);
345 private boolean isConcreteInternalPort(NodeTemplate nodeTemplate) {
346 //Check if node template contains a link requirement
347 List<Map<String, RequirementAssignment>> requirements = nodeTemplate.getRequirements();
348 if (Objects.nonNull(requirements)) {
349 for (Map<String, RequirementAssignment> requirement : requirements) {
350 String requirementId = requirement.keySet().iterator().next();
351 if (requirementId.equals(ToscaConstants.LINK_REQUIREMENT_ID)) {