2 * Copyright © 2016-2018 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.tosca.datatypes.ToscaNodeType;
25 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
26 import org.openecomp.sdc.tosca.datatypes.model.Import;
27 import org.openecomp.sdc.tosca.datatypes.model.NodeTemplate;
28 import org.openecomp.sdc.tosca.datatypes.model.RequirementAssignment;
29 import org.openecomp.sdc.tosca.datatypes.model.ServiceTemplate;
30 import org.openecomp.sdc.tosca.services.DataModelUtil;
31 import org.openecomp.sdc.tosca.services.ToscaConstants;
32 import org.openecomp.sdc.tosca.services.ToscaUtil;
33 import org.openecomp.sdc.translator.services.heattotosca.HeatToToscaUtil;
34 import org.openecomp.sdc.translator.services.heattotosca.globaltypes.GlobalTypesGenerator;
36 import java.util.ArrayList;
37 import java.util.Arrays;
38 import java.util.HashMap;
39 import java.util.HashSet;
40 import java.util.LinkedList;
41 import java.util.List;
43 import java.util.Objects;
44 import java.util.Optional;
46 import java.util.stream.Collectors;
48 import static org.openecomp.sdc.tosca.services.DataModelUtil.getClonedObject;
49 import static org.openecomp.sdc.tosca.services.ToscaConstants.PORT_MIRRORING_CAPABILITY_CP_PROPERTY_NAME;
50 import static org.openecomp.sdc.tosca.services.ToscaConstants.PORT_MIRRORING_CAPABILITY_ID;
52 public class PortMirroringEnricher {
53 //Map of service template file name and map of all port node template ids, node template
54 private Map<String, Map<String, NodeTemplate>> portNodeTemplates = new HashMap<>();
55 //Map of service template file name and map of external port node template ids, node template
56 private Map<String, Map<String, NodeTemplate>> externalPortNodeTemplates = new HashMap<>();
57 //Map of substitution service template name and the list of ports with link requirement from
59 private Map<String, List<String>> portNodeTemplateIdsFromAbstract = new HashMap<>();
60 private Map<String, ServiceTemplate> globalTypesServiceTemplate =
61 GlobalTypesGenerator.getGlobalTypesServiceTemplate(OnboardingTypesEnum.ZIP);
64 * Enrich tosca for port mirroring.
66 * @param toscaServiceModel the tosca service model
67 * @return the map Error descriptor map
69 public Map<String, List<ErrorMessage>> enrich(ToscaServiceModel toscaServiceModel) {
70 Map<String, List<ErrorMessage>> errors = new HashMap<>();
71 Map<String, ServiceTemplate> serviceTemplates = toscaServiceModel.getServiceTemplates();
72 serviceTemplates.entrySet().stream()
73 //Skipping the service templates which do not contain topology template
74 .filter(serviceTemplateEntry -> serviceTemplateEntry.getValue()
75 .getTopology_template() != null)
76 .forEach(serviceTemplateEntry ->
77 //Collect all the ports across all the service templates
78 collectPorts(serviceTemplateEntry.getValue()));
79 //Collect External ports from the list of all ports collected above
80 filterExternalPorts();
81 //Handle external port changes
82 handleExternalPorts(toscaServiceModel);
86 private void collectPorts(ServiceTemplate serviceTemplate) {
87 Map<String, NodeTemplate> nodeTemplates =
88 serviceTemplate.getTopology_template().getNode_templates();
89 if (Objects.nonNull(nodeTemplates)) {
90 //Get all concrete port node templates from the service template
91 Map<String, NodeTemplate> serviceTemplatePortNodeTemplates = nodeTemplates.entrySet().stream()
92 .filter(nodeTemplateEntry -> (Objects.nonNull(nodeTemplateEntry.getValue()))
93 && (isPortNodeTemplate(nodeTemplateEntry.getValue().getType())))
94 .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
96 portNodeTemplates.put(ToscaUtil.getServiceTemplateFileName(serviceTemplate),
97 serviceTemplatePortNodeTemplates);
99 //Get all linked internal ports from abstract node template link requirements
100 collectLinkedInternalPorts(nodeTemplates);
104 private void collectLinkedInternalPorts(Map<String, NodeTemplate> nodeTemplates) {
105 List<String> abstractLinkedPortNodeTemplates = new ArrayList<>();
106 for (Map.Entry<String, NodeTemplate> nodeTemplateEntry : nodeTemplates.entrySet()) {
107 NodeTemplate nodeTemplate = nodeTemplateEntry.getValue();
108 if (isSubstitutableNodeTemplate(nodeTemplate)) {
109 List<Map<String, RequirementAssignment>> requirements = nodeTemplate.getRequirements();
110 if (Objects.isNull(requirements)) {
114 requirements.forEach(requirement -> addInternalPortToAbstractNode(requirement,
115 abstractLinkedPortNodeTemplates));
117 if (CollectionUtils.isNotEmpty(abstractLinkedPortNodeTemplates)) {
118 //Populate a map of the substitution service templates and list of internal ports
119 addCollectedPortsToAbstractServiceTemplatePortMap(nodeTemplate,
120 abstractLinkedPortNodeTemplates);
126 private void addInternalPortToAbstractNode(Map<String, RequirementAssignment> requirement,
127 List<String> abstractLinkedPortNodeTemplates) {
128 String requirementId = requirement.keySet().iterator().next();
129 String abstractLinkRequirementIdPrefix = ToscaConstants.LINK_REQUIREMENT_ID + "_";
130 if (requirementId.startsWith(abstractLinkRequirementIdPrefix)) {
131 //Collect port node template ids from the link requirement ids in the abstract
133 abstractLinkedPortNodeTemplates.add(requirementId.substring(requirementId
138 private void addCollectedPortsToAbstractServiceTemplatePortMap(NodeTemplate nodeTemplate,
139 List<String> abstractLinkedPortNodeTemplates) {
140 String substitutionServiceTemplateName;
141 if (nodeTemplate.getProperties() != null) {
142 Map serviceTemplateFilter = (Map<String, Object>) nodeTemplate.getProperties()
143 .get(ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME);
144 substitutionServiceTemplateName = (String)
145 serviceTemplateFilter.get(ToscaConstants.SUBSTITUTE_SERVICE_TEMPLATE_PROPERTY_NAME);
146 if (Objects.nonNull(substitutionServiceTemplateName)) {
147 if (portNodeTemplateIdsFromAbstract.containsKey(substitutionServiceTemplateName)) {
148 List<String> portList =
149 portNodeTemplateIdsFromAbstract.get(substitutionServiceTemplateName);
150 portList.addAll(abstractLinkedPortNodeTemplates);
151 portNodeTemplateIdsFromAbstract.put(substitutionServiceTemplateName, portList);
153 portNodeTemplateIdsFromAbstract.put(substitutionServiceTemplateName,
154 abstractLinkedPortNodeTemplates);
160 private void filterExternalPorts() {
161 for (Map.Entry<String, Map<String, NodeTemplate>> portNodeTemplateEntry : portNodeTemplates
163 Map<String, NodeTemplate> externalPorts = new HashMap<>();
164 String serviceTemplateFileName = portNodeTemplateEntry.getKey();
165 Map<String, NodeTemplate> portNodeTemplateMap = portNodeTemplateEntry.getValue();
166 for (Map.Entry<String, NodeTemplate> portNodeTemplate : portNodeTemplateMap.entrySet()) {
167 String nodeTemplateId = portNodeTemplate.getKey();
168 NodeTemplate nodeTemplate = portNodeTemplate.getValue();
169 if (!isInternalPort(serviceTemplateFileName, nodeTemplateId, nodeTemplate)) {
171 externalPorts.putIfAbsent(nodeTemplateId, nodeTemplate);
174 externalPortNodeTemplates.putIfAbsent(serviceTemplateFileName, externalPorts);
178 private void updateExternalPortNodeTemplate(NodeTemplate externalPortNodeTemplate) {
179 String currentPortNodeType = externalPortNodeTemplate.getType();
180 if (currentPortNodeType.equals(ToscaNodeType.CONTRAIL_PORT)) {
181 //Set external contrail port node type
182 externalPortNodeTemplate.setType(ToscaNodeType.EXTERNAL_CONTRAIL_PORT);
183 } else if (currentPortNodeType.equals(ToscaNodeType.CONTRAILV2_VIRTUAL_MACHINE_INTERFACE)) {
184 //Set external contrail VMI port node type
185 externalPortNodeTemplate.setType(ToscaNodeType.EXTERNAL_VMI_PORT);
186 } else if (currentPortNodeType.equals(ToscaNodeType.NEUTRON_PORT)) {
187 //Set external neutron port node type
188 externalPortNodeTemplate.setType(ToscaNodeType.EXTERNAL_NEUTRON_PORT);
191 addPortMirroringCapability(externalPortNodeTemplate);
194 private void handleExternalPorts(ToscaServiceModel toscaServiceModel) {
196 for (Map.Entry<String, Map<String, NodeTemplate>> entry : externalPortNodeTemplates
198 String serviceTemplateName = entry.getKey();
199 ServiceTemplate serviceTemplate =
200 toscaServiceModel.getServiceTemplates().get(serviceTemplateName);
201 Map<String, NodeTemplate> externalNodeTemplates = entry.getValue();
202 if (MapUtils.isEmpty(externalNodeTemplates)) {
206 for (Map.Entry<String, NodeTemplate> externalNodeTemplate : externalNodeTemplates
208 String externalPortNodeTemplateId = externalNodeTemplate.getKey();
209 updateExternalPortNodeTemplate(externalNodeTemplate.getValue());
210 if (serviceTemplate.getTopology_template().getSubstitution_mappings() != null) {
211 //Add port mirroring capability to substitution mapping for external ports
212 addPortMirroringSubstitutionMappingCapability(serviceTemplate,
213 externalPortNodeTemplateId);
216 addGlobalTypeImport(serviceTemplate);
220 private void addPortMirroringSubstitutionMappingCapability(ServiceTemplate serviceTemplate,
221 String externalPortNodeTemplateId) {
222 List<String> portMirroringCapability = new LinkedList<>();
223 portMirroringCapability.add(externalPortNodeTemplateId);
224 portMirroringCapability.add(PORT_MIRRORING_CAPABILITY_ID);
225 String substitutionMappingCapabilityId = PORT_MIRRORING_CAPABILITY_ID + "_"
226 + externalPortNodeTemplateId;
227 DataModelUtil.addSubstitutionMappingCapability(serviceTemplate,
228 substitutionMappingCapabilityId, portMirroringCapability);
231 private void addPortMirroringCapability(NodeTemplate portNodeTemplate) {
232 Map<String, Object> portMirroringCapabilityProperties = new HashMap<>();
233 PortMirroringConnectionPointDescription connectionPoint = new
234 PortMirroringConnectionPointDescription();
235 //Get Network role property
236 if (Objects.nonNull(portNodeTemplate.getProperties())) {
237 Object networkRolePropertyValue =
238 portNodeTemplate.getProperties().get(ToscaConstants.PORT_NETWORK_ROLE_PROPERTY_NAME);
239 if (Objects.nonNull(networkRolePropertyValue)) {
240 Object portMirroringNetworkRolePropertyVal = getClonedObject(networkRolePropertyValue);
241 connectionPoint.setNetwork_role(portMirroringNetworkRolePropertyVal);
244 //Get NFC_Type from the binding requirement node
245 if (Objects.nonNull(portNodeTemplate.getRequirements())) {
246 Optional<List<RequirementAssignment>> requirementAssignment =
247 DataModelUtil.getRequirementAssignment(portNodeTemplate.getRequirements(), ToscaConstants
248 .BINDING_REQUIREMENT_ID);
249 if (requirementAssignment.isPresent()) {
250 RequirementAssignment bindingRequirementAssignment = requirementAssignment.get().get(0);
251 String node = bindingRequirementAssignment.getNode();
252 connectionPoint.setNfc_type(node);
256 if (!connectionPoint.isEmpty()) {
257 portMirroringCapabilityProperties.put(PORT_MIRRORING_CAPABILITY_CP_PROPERTY_NAME,
259 DataModelUtil.addNodeTemplateCapability(portNodeTemplate,
260 PORT_MIRRORING_CAPABILITY_ID, portMirroringCapabilityProperties, null);
264 private void addGlobalTypeImport(ServiceTemplate serviceTemplate) {
265 List<Map<String, Import>> imports = serviceTemplate.getImports();
266 Map<String, Import> openecompIndexImport = new HashMap<>();
267 openecompIndexImport.put("openecomp_index",
268 HeatToToscaUtil.createServiceTemplateImport(globalTypesServiceTemplate
269 .get("openecomp/_index.yml")));
270 imports.add(openecompIndexImport);
273 private boolean isPortNodeTemplate(String nodeType) {
274 //Check if node corresponds to a concrete port node
275 Set<String> portNodeTypes = getPortNodeTypes();
276 return Objects.nonNull(nodeType)
277 && portNodeTypes.contains(nodeType);
280 private Set<String> getPortNodeTypes() {
281 return new HashSet<>(Arrays.asList(ToscaNodeType.NEUTRON_PORT,
282 ToscaNodeType.CONTRAILV2_VIRTUAL_MACHINE_INTERFACE,
283 ToscaNodeType.CONTRAIL_PORT));
286 private boolean isSubstitutableNodeTemplate(NodeTemplate nodeTemplate) {
287 return Objects.nonNull(nodeTemplate.getDirectives())
288 && nodeTemplate.getDirectives()
289 .contains(ToscaConstants.NODE_TEMPLATE_DIRECTIVE_SUBSTITUTABLE);
292 private boolean isInternalPort(String serviceTemplateFileName, String nodeTemplateId,
293 NodeTemplate nodeTemplate) {
294 return isAbstractInternalPort(serviceTemplateFileName, nodeTemplateId)
295 || isConcreteInternalPort(nodeTemplate);
298 private boolean isAbstractInternalPort(String serviceTemplateFileName, String nodeTemplateId) {
299 //Check if port corresponds to an abstract internal port
300 return portNodeTemplateIdsFromAbstract.containsKey(serviceTemplateFileName)
301 && portNodeTemplateIdsFromAbstract.get(serviceTemplateFileName).contains(nodeTemplateId);
305 private boolean isConcreteInternalPort(NodeTemplate nodeTemplate) {
306 //Check if node template contains a link requirement
307 List<Map<String, RequirementAssignment>> requirements = nodeTemplate.getRequirements();
308 if (Objects.nonNull(requirements)) {
309 for (Map<String, RequirementAssignment> requirement : requirements) {
310 String requirementId = requirement.keySet().iterator().next();
311 if (requirementId.equals(ToscaConstants.LINK_REQUIREMENT_ID)) {