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.ToscaNodeType;
9 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
10 import org.openecomp.sdc.tosca.datatypes.model.CapabilityAssignment;
11 import org.openecomp.sdc.tosca.datatypes.model.Import;
12 import org.openecomp.sdc.tosca.datatypes.model.NodeTemplate;
13 import org.openecomp.sdc.tosca.datatypes.model.PropertyDefinition;
14 import org.openecomp.sdc.tosca.datatypes.model.RequirementAssignment;
15 import org.openecomp.sdc.tosca.datatypes.model.ServiceTemplate;
16 import org.openecomp.sdc.tosca.services.DataModelUtil;
17 import org.openecomp.sdc.tosca.services.ToscaConstants;
18 import org.openecomp.sdc.tosca.services.ToscaUtil;
19 import org.openecomp.sdc.translator.services.heattotosca.HeatToToscaUtil;
20 import org.openecomp.sdc.translator.services.heattotosca.globaltypes.GlobalTypesGenerator;
22 import java.util.ArrayList;
23 import java.util.HashMap;
24 import java.util.LinkedList;
25 import java.util.List;
27 import java.util.Objects;
28 import java.util.Optional;
29 import java.util.stream.Collectors;
31 import static org.openecomp.sdc.tosca.services.DataModelUtil.getClonedObject;
32 import static org.openecomp.sdc.tosca.services.ToscaConstants.PORT_MIRRORING_CAPABILITY_CP_PROPERTY_NAME;
33 import static org.openecomp.sdc.tosca.services.ToscaConstants.PORT_MIRRORING_CAPABILITY_ID;
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
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();
48 * Enrich tosca for port mirroring.
50 * @param toscaServiceModel the tosca service model
51 * @return the map Error descriptor map
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);
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 -> isPortNodeTemplate(nodeTemplateEntry.getValue()))
79 .collect(Collectors.toMap(nodeTemplateEntry -> nodeTemplateEntry.getKey(),
80 nodeTemplateEntry -> nodeTemplateEntry.getValue()));
82 portNodeTemplates.put(ToscaUtil.getServiceTemplateFileName(serviceTemplate),
83 serviceTemplatePortNodeTemplates);
85 //Get all linked internal ports from abstract node template link requirements
86 List<String> abstractLinkedPortNodeTemplates = new ArrayList<>();
87 for (Map.Entry<String, NodeTemplate> nodeTemplateEntry : nodeTemplates.entrySet()) {
88 NodeTemplate nodeTemplate = nodeTemplateEntry.getValue();
89 if (isSubstitutableNodeTemplate(nodeTemplate)) {
90 List<Map<String, RequirementAssignment>> requirements = nodeTemplate.getRequirements();
91 if (Objects.nonNull(requirements)) {
92 for (Map<String, RequirementAssignment> requirement : requirements) {
93 String requirementId = requirement.keySet().iterator().next();
94 String abstractLinkRequirementIdPrefix = ToscaConstants.LINK_REQUIREMENT_ID + "_";
95 if (requirementId.startsWith(abstractLinkRequirementIdPrefix)) {
96 //Collect port node template ids from the link requirement ids in the abstract
98 abstractLinkedPortNodeTemplates.add(requirementId.substring(requirementId
103 if (CollectionUtils.isNotEmpty(abstractLinkedPortNodeTemplates)) {
104 //Populate a map of the substitution service templates and list of internal ports
105 addCollectedPortsToAbstractServiceTemplatePortMap(nodeTemplate,
106 abstractLinkedPortNodeTemplates);
113 private void addCollectedPortsToAbstractServiceTemplatePortMap(NodeTemplate nodeTemplate,
115 abstractLinkedPortNodeTemplates) {
116 String substitutionServiceTemplateName = null;
117 if (nodeTemplate.getProperties() != null) {
118 Map serviceTemplateFilter = (Map<String, Object>) nodeTemplate.getProperties()
119 .get(ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME);
120 substitutionServiceTemplateName = (String)
121 serviceTemplateFilter.get(ToscaConstants.SUBSTITUTE_SERVICE_TEMPLATE_PROPERTY_NAME);
122 if (Objects.nonNull(substitutionServiceTemplateName)) {
123 if (portNodeTemplateIdsFromAbstract.containsKey(substitutionServiceTemplateName)) {
124 List<String> portList =
125 portNodeTemplateIdsFromAbstract.get(substitutionServiceTemplateName);
126 portList.addAll(abstractLinkedPortNodeTemplates);
127 portNodeTemplateIdsFromAbstract.put(substitutionServiceTemplateName, portList);
129 portNodeTemplateIdsFromAbstract.put(substitutionServiceTemplateName,
130 abstractLinkedPortNodeTemplates);
136 private void filterExternalPorts(ToscaServiceModel toscaServiceModel) {
137 for (Map.Entry<String, Map<String, NodeTemplate>> portNodeTemplateEntry : portNodeTemplates
139 Map<String, NodeTemplate> externalPorts = new HashMap<>();
140 String serviceTemplateFileName = portNodeTemplateEntry.getKey();
141 Map<String, NodeTemplate> portNodeTemplateMap = portNodeTemplateEntry.getValue();
142 for (Map.Entry<String, NodeTemplate> portNodeTemplate : portNodeTemplateMap.entrySet()) {
143 String nodeTemplateId = portNodeTemplate.getKey();
144 NodeTemplate nodeTemplate = portNodeTemplate.getValue();
145 String newPortNodeType = nodeTemplate.getType();
146 if (!isInternalPort(serviceTemplateFileName, nodeTemplateId, nodeTemplate)) {
148 externalPorts.putIfAbsent(nodeTemplateId, nodeTemplate);
151 externalPortNodeTemplates.putIfAbsent(serviceTemplateFileName, externalPorts);
155 private void updateExternalPortNodeTemplate(NodeTemplate externalPortNodeTemplate,
156 ToscaServiceModel toscaServiceModel) {
157 String currentPortNodeType = externalPortNodeTemplate.getType();
158 if (currentPortNodeType.equals(ToscaNodeType.CONTRAIL_PORT)
159 || currentPortNodeType.equals(ToscaNodeType.CONTRAILV2_VIRTUAL_MACHINE_INTERFACE)) {
160 //Set external contrail port node type
161 externalPortNodeTemplate.setType(ToscaNodeType.EXTERNAL_CONTRAIL_PORT);
162 addPortMirroringCapability(externalPortNodeTemplate);
163 } else if (currentPortNodeType.equals(ToscaNodeType.NEUTRON_PORT)) {
164 //Set external neutron port node type
165 externalPortNodeTemplate.setType(ToscaNodeType.EXTERNAL_NEUTRON_PORT);
166 addPortMirroringCapability(externalPortNodeTemplate);
170 private void handleExternalPorts(ToscaServiceModel toscaServiceModel) {
172 for (Map.Entry<String, Map<String, NodeTemplate>> entry : externalPortNodeTemplates
174 String serviceTemplateName = entry.getKey();
175 ServiceTemplate serviceTemplate =
176 toscaServiceModel.getServiceTemplates().get(serviceTemplateName);
177 Map<String, NodeTemplate> externalNodeTemplates = entry.getValue();
178 if (MapUtils.isNotEmpty(externalNodeTemplates)) {
179 for (Map.Entry<String, NodeTemplate> externalNodeTemplate : externalNodeTemplates
181 String externalPortNodeTemplateId = externalNodeTemplate.getKey();
182 updateExternalPortNodeTemplate(externalNodeTemplate.getValue(), toscaServiceModel);
183 if (serviceTemplate.getTopology_template().getSubstitution_mappings() != null) {
184 //Add port mirroring capability to substitution mapping for external ports
185 addPortMirroringSubstitutionMappingCapability(serviceTemplate,
186 externalPortNodeTemplateId);
188 handleExternalPortProperties(externalNodeTemplate.getValue());
190 addGlobalTypeImport(serviceTemplate);
195 private void handleExternalPortProperties(NodeTemplate portNodeTemplate) {
197 ServiceTemplate serviceTemplate = globalTypesServiceTemplate.get("openecomp/nodes.yml");
198 String externalPortType = portNodeTemplate.getType();
199 Map<String, PropertyDefinition> globalTypesportProperties = new HashMap<>();
200 globalTypesportProperties.putAll(
201 serviceTemplate.getNode_types().get("org.openecomp.resource.cp.nodes.network.Port")
203 globalTypesportProperties
204 .putAll(serviceTemplate.getNode_types().get(externalPortType).getProperties());
206 Map<String, Object> properties = portNodeTemplate.getProperties();
207 Map<String, Object> filteredProperties = new HashMap<>();
209 if (MapUtils.isEmpty(properties)) {
213 for (Map.Entry<String, Object> propertyEntry : properties.entrySet()) {
214 if (globalTypesportProperties.containsKey(propertyEntry.getKey())) {
215 filteredProperties.put(propertyEntry.getKey(), propertyEntry.getValue());
219 if (!MapUtils.isEmpty(filteredProperties)) {
220 portNodeTemplate.setProperties(filteredProperties);
222 portNodeTemplate.setProperties(null);
227 private void addPortMirroringSubstitutionMappingCapability(ServiceTemplate serviceTemplate,
228 String externalPortNodeTemplateId) {
229 List<String> portMirroringCapability = new LinkedList<>();
230 portMirroringCapability.add(externalPortNodeTemplateId);
231 portMirroringCapability.add(PORT_MIRRORING_CAPABILITY_ID);
232 String substitutionMappingCapabilityId = PORT_MIRRORING_CAPABILITY_ID + "_"
233 + externalPortNodeTemplateId;
234 DataModelUtil.addSubstitutionMappingCapability(serviceTemplate,
235 substitutionMappingCapabilityId, portMirroringCapability);
238 private void addPortMirroringCapability(NodeTemplate portNodeTemplate) {
239 List<Map<String, CapabilityAssignment>> capabilities = portNodeTemplate.getCapabilities();
240 if (Objects.isNull(capabilities)) {
241 capabilities = new ArrayList<>();
243 Map<String, Object> portMirroringCapabilityProperties = new HashMap<>();
244 PortMirroringConnectionPointDescription connectionPoint = new
245 PortMirroringConnectionPointDescription();
246 //Get Network role property
247 if (Objects.nonNull(portNodeTemplate.getProperties())) {
248 Object networkRolePropertyValue =
249 portNodeTemplate.getProperties().get(ToscaConstants.PORT_NETWORK_ROLE_PROPERTY_NAME);
250 if (Objects.nonNull(networkRolePropertyValue)) {
251 Object portMirroringNetworkRolePropertyVal = getClonedObject(networkRolePropertyValue);
252 connectionPoint.setNetwork_role(portMirroringNetworkRolePropertyVal);
255 //Get NFC_Type from the binding requirement node
256 if (Objects.nonNull(portNodeTemplate.getRequirements())) {
257 Optional<List<RequirementAssignment>> requirementAssignment =
258 DataModelUtil.getRequirementAssignment(portNodeTemplate.getRequirements(), ToscaConstants
259 .BINDING_REQUIREMENT_ID);
260 if (requirementAssignment.isPresent()) {
261 RequirementAssignment bindingRequirementAssignment = requirementAssignment.get().get(0);
262 String node = bindingRequirementAssignment.getNode();
263 connectionPoint.setNfc_type(node);
267 if (!connectionPoint.isEmpty()) {
268 portMirroringCapabilityProperties.put(PORT_MIRRORING_CAPABILITY_CP_PROPERTY_NAME,
270 DataModelUtil.addNodeTemplateCapability(portNodeTemplate,
271 PORT_MIRRORING_CAPABILITY_ID, portMirroringCapabilityProperties, null);
275 private void addGlobalTypeImport(ServiceTemplate serviceTemplate) {
276 List<Map<String, Import>> imports = serviceTemplate.getImports();
277 Map<String, Import> openecompIndexImport = new HashMap<>();
278 openecompIndexImport.put("openecomp_index",
279 HeatToToscaUtil.createServiceTemplateImport(globalTypesServiceTemplate
280 .get("openecomp/_index.yml")));
281 imports.add(openecompIndexImport);
284 private boolean isPortNodeTemplate(NodeTemplate nodeTemplate) {
285 String nodeType = nodeTemplate.getType();
286 //Check if node corresponds to a concrete port node
287 if (nodeType.equals(ToscaNodeType.NEUTRON_PORT)
288 || nodeType.equals(ToscaNodeType.CONTRAILV2_VIRTUAL_MACHINE_INTERFACE)
289 || nodeType.equals(ToscaNodeType.CONTRAIL_PORT)
290 || nodeType.equals(ToscaNodeType.NETWORK_PORT)
291 || nodeType.equals(ToscaNodeType.NATIVE_NETWORK_PORT)) {
297 private boolean isSubstitutableNodeTemplate(NodeTemplate nodeTemplate) {
298 if (Objects.nonNull(nodeTemplate.getDirectives())) {
299 return nodeTemplate.getDirectives().contains(ToscaConstants
300 .NODE_TEMPLATE_DIRECTIVE_SUBSTITUTABLE);
305 private boolean isInternalPort(String serviceTemplateFileName, String nodeTemplateId,
306 NodeTemplate nodeTemplate) {
307 return isAbstractInternalPort(serviceTemplateFileName, nodeTemplateId)
308 || isConcreteInternalPort(nodeTemplate);
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);
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)) {