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