658fc987253eee1d8b0fcd3fab70c1b0bbf93a3f
[sdc.git] /
1 /*
2  * Copyright © 2016-2018 European Support Limited
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 package org.openecomp.sdc.enrichment.impl.tosca;
18
19 import static org.openecomp.sdc.enrichment.impl.util.EnrichmentConstants.HIGH_AVAIL_MODE;
20 import static org.openecomp.sdc.enrichment.impl.util.EnrichmentConstants.MANDATORY;
21 import static org.openecomp.sdc.enrichment.impl.util.EnrichmentConstants.MAX_INSTANCES;
22 import static org.openecomp.sdc.enrichment.impl.util.EnrichmentConstants.MIN_INSTANCES;
23 import static org.openecomp.sdc.enrichment.impl.util.EnrichmentConstants.NFC_FUNCTION;
24 import static org.openecomp.sdc.enrichment.impl.util.EnrichmentConstants.NFC_NAMING_CODE;
25 import static org.openecomp.sdc.enrichment.impl.util.EnrichmentConstants.VFC_CODE;
26 import static org.openecomp.sdc.enrichment.impl.util.EnrichmentConstants.VM_TYPE_TAG;
27 import static org.openecomp.sdc.tosca.datatypes.ToscaCapabilityType.NATIVE_NODE;
28 import static org.openecomp.sdc.tosca.datatypes.ToscaNodeType.MULTIDEPLOYMENTFLAVOR_NODE_TYPE;
29 import static org.openecomp.sdc.tosca.datatypes.ToscaNodeType.VFC_ABSTRACT_SUBSTITUTE;
30 import static org.openecomp.sdc.tosca.datatypes.ToscaRelationshipType.NATIVE_DEPENDS_ON;
31 import static org.openecomp.sdc.tosca.services.ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME;
32 import static org.openecomp.sdc.translator.services.heattotosca.Constants.VNF_NODE_TEMPLATE_ID_SUFFIX;
33
34 import java.util.ArrayList;
35 import java.util.HashMap;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.Objects;
39 import java.util.Optional;
40
41 import org.apache.commons.collections4.CollectionUtils;
42 import org.apache.commons.lang3.StringUtils;
43 import org.onap.sdc.tosca.datatypes.model.NodeTemplate;
44 import org.onap.sdc.tosca.datatypes.model.NodeType;
45 import org.onap.sdc.tosca.datatypes.model.RequirementAssignment;
46 import org.onap.sdc.tosca.datatypes.model.RequirementDefinition;
47 import org.onap.sdc.tosca.datatypes.model.ServiceTemplate;
48 import org.openecomp.sdc.datatypes.error.ErrorMessage;
49 import org.openecomp.sdc.tosca.datatypes.ToscaElementTypes;
50 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
51 import org.openecomp.sdc.tosca.services.DataModelUtil;
52 import org.openecomp.sdc.tosca.services.ToscaAnalyzerService;
53 import org.openecomp.sdc.tosca.services.ToscaConstants;
54 import org.openecomp.sdc.tosca.services.impl.ToscaAnalyzerServiceImpl;
55 import org.openecomp.sdc.versioning.dao.types.Version;
56
57 public class AbstractSubstituteToscaEnricher {
58
59     private ToscaAnalyzerService toscaAnalyzerService;
60     private ComponentQuestionnaireData componentQuestionnaireData;
61
62
63     public Map<String, List<ErrorMessage>> enrich(ToscaServiceModel toscaModel, String vspId, Version version) {
64         componentQuestionnaireData = getComponentQuestionnaireData();
65         toscaAnalyzerService = new ToscaAnalyzerServiceImpl();
66
67         Map<String, Map<String, Object>> componentProperties =
68                 componentQuestionnaireData.getPropertiesfromCompQuestionnaire(vspId, version);
69
70         final Map<String, List<String>> sourceToTargetDependencies = componentQuestionnaireData
71                                                                              .populateDependencies(vspId, version,
72                                                                                      componentQuestionnaireData
73                                                                                       .getSourceToTargetComponent());
74         Map<String, List<ErrorMessage>> errors = new HashMap<>();
75
76         final ServiceTemplate serviceTemplate =
77                 toscaModel.getServiceTemplates().get(toscaModel.getEntryDefinitionServiceTemplate());
78
79         if (serviceTemplate == null) {
80             return errors;
81         }
82
83         final Map<String, NodeTemplate> nodeTemplates = serviceTemplate.getTopology_template().getNode_templates();
84         if (nodeTemplates == null) {
85             return errors;
86         }
87
88         final Map<String, List<String>> componentDisplayNameToNodeTemplateIds =
89                 populateAllNodeTemplateIdForComponent(nodeTemplates, serviceTemplate, toscaModel);
90
91         nodeTemplates.keySet().forEach(nodeTemplateId -> {
92             final NodeTemplate nodeTemplate =
93                     toscaAnalyzerService.getNodeTemplateById(serviceTemplate, nodeTemplateId).orElse(null);
94
95             if (nodeTemplate != null && toscaAnalyzerService.isTypeOf(nodeTemplate, VFC_ABSTRACT_SUBSTITUTE,
96                     serviceTemplate, toscaModel)) {
97
98                 String componentDisplayName = getComponentDisplayName(nodeTemplateId, nodeTemplate);
99
100                 enrichProperties(nodeTemplate, componentDisplayName, componentProperties);
101
102                 enrichRequirements(sourceToTargetDependencies, componentDisplayName, nodeTemplate,
103                         componentDisplayNameToNodeTemplateIds, serviceTemplate, toscaModel);
104             }
105         });
106         return errors;
107     }
108
109     private void enrichProperties(NodeTemplate nodeTemplate, String componentDisplayName,
110             Map<String, Map<String, Object>> componentProperties) {
111         setProperty(nodeTemplate, VM_TYPE_TAG, componentDisplayName);
112
113         if (componentProperties != null && componentProperties.containsKey(componentDisplayName)) {
114             final String mandatory =
115                     getValueFromQuestionnaireDetails(componentProperties, componentDisplayName, MANDATORY);
116
117             boolean isServiceTemplateFilterNotExists = false;
118             if (!StringUtils.isEmpty(mandatory)) {
119                 Map<String, Object> innerProps = (Map<String, Object>) nodeTemplate.getProperties()
120                                                                    .get(SERVICE_TEMPLATE_FILTER_PROPERTY_NAME);
121
122                 if (innerProps == null) {
123                     innerProps = new HashMap<>();
124                     isServiceTemplateFilterNotExists = true;
125                 }
126                 Optional<Boolean> mandatoryValue = getValue(mandatory);
127                 if (mandatoryValue.isPresent()) {
128                     innerProps.put(MANDATORY, mandatoryValue.get());
129                 }
130
131                 if (isServiceTemplateFilterNotExists) {
132                     nodeTemplate.getProperties().put(SERVICE_TEMPLATE_FILTER_PROPERTY_NAME, innerProps);
133                 }
134             }
135
136             setProperty(nodeTemplate, HIGH_AVAIL_MODE,
137                     getValueFromQuestionnaireDetails(componentProperties, componentDisplayName,
138                             HIGH_AVAIL_MODE));
139
140             setProperty(nodeTemplate, NFC_NAMING_CODE,
141                     getValueFromQuestionnaireDetails(componentProperties, componentDisplayName,
142                             NFC_NAMING_CODE));
143
144             setProperty(nodeTemplate, VFC_CODE,
145                     getValueFromQuestionnaireDetails(componentProperties, componentDisplayName, VFC_CODE));
146
147             setProperty(nodeTemplate, NFC_FUNCTION,
148                     getValueFromQuestionnaireDetails(componentProperties, componentDisplayName, NFC_FUNCTION));
149
150             if (componentProperties.get(componentDisplayName).get(MIN_INSTANCES) != null) {
151                 nodeTemplate.getProperties().put(MIN_INSTANCES,
152                         componentProperties.get(componentDisplayName).get(MIN_INSTANCES));
153             }
154
155             if (componentProperties.get(componentDisplayName).get(MAX_INSTANCES) != null) {
156                 nodeTemplate.getProperties().put(MAX_INSTANCES,
157                         componentProperties.get(componentDisplayName).get(MAX_INSTANCES));
158             }
159         }
160     }
161
162     private Map<String, List<String>> populateAllNodeTemplateIdForComponent(Map<String, NodeTemplate> nodeTemplates,
163                                                                                    ServiceTemplate serviceTemplate,
164                                                                                    ToscaServiceModel toscaModel) {
165
166
167         Map<String, List<String>> componentDisplayNameToNodeTempalteIds = new HashMap<>();
168
169         //set dependency target
170         nodeTemplates.keySet().forEach(nodeTemplateId -> {
171             final NodeTemplate nodeTemplate =
172                     toscaAnalyzerService.getNodeTemplateById(serviceTemplate, nodeTemplateId).orElse(null);
173
174             if (nodeTemplate != null &&
175                     toscaAnalyzerService.isTypeOf(nodeTemplate, VFC_ABSTRACT_SUBSTITUTE, serviceTemplate, toscaModel)) {
176
177                 String componentDisplayName = getComponentDisplayName(nodeTemplateId, nodeTemplate);
178
179                 if (componentDisplayNameToNodeTempalteIds.containsKey(componentDisplayName)) {
180                     componentDisplayNameToNodeTempalteIds.get(componentDisplayName).add(nodeTemplateId);
181                 } else {
182                     List<String> nodeTemplateIds = new ArrayList<>();
183                     nodeTemplateIds.add(nodeTemplateId);
184                     componentDisplayNameToNodeTempalteIds.put(componentDisplayName, nodeTemplateIds);
185                 }
186
187             }
188         });
189
190         return componentDisplayNameToNodeTempalteIds;
191     }
192
193     private void enrichRequirements(Map<String, List<String>> sourceToTargetDependencies, String componentDisplayName,
194                                            NodeTemplate nodeTemplate,
195                                            Map<String, List<String>> componentDisplayNameToNodeTempalteIds,
196                                            ServiceTemplate serviceTemplate, ToscaServiceModel toscaServiceModel) {
197         final List<String> targets = sourceToTargetDependencies.get(componentDisplayName);
198         if (CollectionUtils.isEmpty(targets)) {
199             return;
200         }
201
202         for (String target : targets) {
203             List<String> targetNodeTemplateIds = componentDisplayNameToNodeTempalteIds.get(target);
204             if (CollectionUtils.isEmpty(targetNodeTemplateIds)) {
205                 continue;
206             }
207             for (String targetNodeTemplateId : targetNodeTemplateIds) {
208                 Optional<String> dependencyRequirementKey =
209                         getDependencyRequirementKey(serviceTemplate, componentDisplayName, nodeTemplate,
210                                 toscaServiceModel);
211                 if (dependencyRequirementKey.isPresent()) {
212                     RequirementAssignment requirementAssignment = new RequirementAssignment();
213                     requirementAssignment.setCapability(NATIVE_NODE);
214                     requirementAssignment.setRelationship(NATIVE_DEPENDS_ON);
215                     requirementAssignment.setNode(targetNodeTemplateId);
216                     DataModelUtil.addRequirementAssignment(nodeTemplate, dependencyRequirementKey.get(),
217                             requirementAssignment);
218                 }
219             }
220         }
221     }
222
223     private Optional<String> getDependencyRequirementKey(ServiceTemplate serviceTemplate, String componentDisplayName,
224                                                                 NodeTemplate nodeTemplate,
225                                                                 ToscaServiceModel toscaServiceModel) {
226         String nodeType = nodeTemplate.getType();
227         NodeType flatNodeType = (NodeType) toscaAnalyzerService.getFlatEntity(ToscaElementTypes.NODE_TYPE, nodeType,
228                 serviceTemplate, toscaServiceModel).getFlatEntity();
229         List<Map<String, RequirementDefinition>> flatNodeTypeRequirements = flatNodeType.getRequirements();
230         if (Objects.isNull(flatNodeTypeRequirements)) {
231             return Optional.empty();
232         }
233         for (Map<String, RequirementDefinition> requirementDefinitionMap : flatNodeTypeRequirements) {
234             String requirementKey = requirementDefinitionMap.keySet().iterator().next();
235             String expectedKey = ToscaConstants.DEPENDS_ON_REQUIREMENT_ID + "_" + componentDisplayName;
236             if (requirementKey.equals(expectedKey)) {
237                 return Optional.of(requirementKey);
238             }
239         }
240         return Optional.empty();
241     }
242
243     private String getComponentDisplayName(String nodeTemplateId, NodeTemplate nodeTemplate) {
244         String componentDisplayName;
245         final String type = nodeTemplate.getType();
246         if (MULTIDEPLOYMENTFLAVOR_NODE_TYPE.equals(type)) {
247             componentDisplayName = nodeTemplateId.substring(0, nodeTemplateId.lastIndexOf(VNF_NODE_TEMPLATE_ID_SUFFIX));
248         } else {
249             String vmType = DataModelUtil.getNamespaceSuffix(type);
250             final String[] removedSuffix = vmType.split("_\\d+");
251             componentDisplayName = removedSuffix[0];
252         }
253         return componentDisplayName;
254     }
255
256     private String getValueFromQuestionnaireDetails(Map<String, Map<String, Object>> componentTypetoParams,
257                                                            String componentDisplayName, String propertyName) {
258         return (String) componentTypetoParams.get(componentDisplayName).get(propertyName);
259     }
260
261     private void setProperty(NodeTemplate nodeTemplate, String key, String value) {
262         if (!StringUtils.isEmpty(value)) {
263             //YamlUtil throws IllegalStateException("duplicate key: " + key) if key is already present.
264             // So first removing and then populating same key with new updated value
265             nodeTemplate.getProperties().remove(key);
266             nodeTemplate.getProperties().put(key, value);
267         }
268     }
269
270     private Optional<Boolean> getValue(String value) {
271         switch (value) {
272             case "YES":
273                 return Optional.of(Boolean.TRUE);
274             case "NO":
275                 return Optional.of(Boolean.FALSE);
276             default:
277                 return Optional.empty();
278         }
279     }
280
281     private ComponentQuestionnaireData getComponentQuestionnaireData() {
282         if (componentQuestionnaireData == null) {
283             componentQuestionnaireData = new ComponentQuestionnaireData();
284         }
285         return componentQuestionnaireData;
286     }
287 }