afc5bd2bdcd711c2e53b8bb1c494ae305962b6b0
[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.ABSTRACT_NODE_TEMPLATE_ID_PREFIX;
33 import static org.openecomp.sdc.translator.services.heattotosca.Constants.VNF_NODE_TEMPLATE_ID_SUFFIX;
34
35 import java.util.ArrayList;
36 import java.util.HashMap;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Objects;
40 import java.util.Optional;
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 (toscaAnalyzerService.isTypeOf(nodeTemplate, VFC_ABSTRACT_SUBSTITUTE, serviceTemplate, toscaModel)) {
96
97                 String componentDisplayName = getComponentDisplayName(nodeTemplateId, nodeTemplate);
98
99                 enrichProperties(nodeTemplate, componentDisplayName, componentProperties);
100
101                 enrichRequirements(sourceToTargetDependencies, componentDisplayName, nodeTemplate,
102                         componentDisplayNameToNodeTemplateIds, serviceTemplate, toscaModel);
103             }
104         });
105         return errors;
106     }
107
108     private void enrichProperties(NodeTemplate nodeTemplate, String componentDisplayName,
109             Map<String, Map<String, Object>> componentProperties) {
110         setProperty(nodeTemplate, VM_TYPE_TAG, componentDisplayName);
111
112         if (componentProperties != null && componentProperties.containsKey(componentDisplayName)) {
113             final String mandatory =
114                     getValueFromQuestionnaireDetails(componentProperties, componentDisplayName, MANDATORY);
115
116             boolean isServiceTemplateFilterNotExists = false;
117             if (!StringUtils.isEmpty(mandatory)) {
118                 Map innerProps = (Map<String, Object>) nodeTemplate.getProperties()
119                                                                    .get(SERVICE_TEMPLATE_FILTER_PROPERTY_NAME);
120
121                 if (innerProps == null) {
122                     innerProps = new HashMap<String, Object>();
123                     isServiceTemplateFilterNotExists = true;
124                 }
125
126                 innerProps.put(MANDATORY, getValue(mandatory));
127
128                 if (isServiceTemplateFilterNotExists) {
129                     nodeTemplate.getProperties().put(SERVICE_TEMPLATE_FILTER_PROPERTY_NAME, innerProps);
130                 }
131             }
132
133             setProperty(nodeTemplate, HIGH_AVAIL_MODE,
134                     getValueFromQuestionnaireDetails(componentProperties, componentDisplayName,
135                             HIGH_AVAIL_MODE));
136
137             setProperty(nodeTemplate, NFC_NAMING_CODE,
138                     getValueFromQuestionnaireDetails(componentProperties, componentDisplayName,
139                             NFC_NAMING_CODE));
140
141             setProperty(nodeTemplate, VFC_CODE,
142                     getValueFromQuestionnaireDetails(componentProperties, componentDisplayName, VFC_CODE));
143
144             setProperty(nodeTemplate, NFC_FUNCTION,
145                     getValueFromQuestionnaireDetails(componentProperties, componentDisplayName, NFC_FUNCTION));
146
147             if (componentProperties.get(componentDisplayName).get(MIN_INSTANCES) != null) {
148                 nodeTemplate.getProperties().put(MIN_INSTANCES,
149                         componentProperties.get(componentDisplayName).get(MIN_INSTANCES));
150             }
151
152             if (componentProperties.get(componentDisplayName).get(MAX_INSTANCES) != null) {
153                 nodeTemplate.getProperties().put(MAX_INSTANCES,
154                         componentProperties.get(componentDisplayName).get(MAX_INSTANCES));
155             }
156         }
157     }
158
159     private Map<String, List<String>> populateAllNodeTemplateIdForComponent(Map<String, NodeTemplate> nodeTemplates,
160                                                                                    ServiceTemplate serviceTemplate,
161                                                                                    ToscaServiceModel toscaModel) {
162
163
164         Map<String, List<String>> componentDisplayNameToNodeTempalteIds = new HashMap<>();
165
166         //set dependency target
167         nodeTemplates.keySet().forEach(nodeTemplateId -> {
168             final NodeTemplate nodeTemplate =
169                     toscaAnalyzerService.getNodeTemplateById(serviceTemplate, nodeTemplateId).orElse(null);
170
171             if (toscaAnalyzerService.isTypeOf(nodeTemplate, VFC_ABSTRACT_SUBSTITUTE, serviceTemplate, toscaModel)) {
172
173                 String componentDisplayName = getComponentDisplayName(nodeTemplateId, nodeTemplate);
174
175                 if (componentDisplayNameToNodeTempalteIds.containsKey(componentDisplayName)) {
176                     componentDisplayNameToNodeTempalteIds.get(componentDisplayName).add(nodeTemplateId);
177                 } else {
178                     List<String> nodeTemplateIds = new ArrayList<>();
179                     nodeTemplateIds.add(nodeTemplateId);
180                     componentDisplayNameToNodeTempalteIds.put(componentDisplayName, nodeTemplateIds);
181                 }
182
183             }
184         });
185
186         return componentDisplayNameToNodeTempalteIds;
187     }
188
189     private void enrichRequirements(Map<String, List<String>> sourceToTargetDependencies, String componentDisplayName,
190                                            NodeTemplate nodeTemplate,
191                                            Map<String, List<String>> componentDisplayNameToNodeTempalteIds,
192                                            ServiceTemplate serviceTemplate, ToscaServiceModel toscaServiceModel) {
193         final List<String> targets = sourceToTargetDependencies.get(componentDisplayName);
194         if (CollectionUtils.isEmpty(targets)) {
195             return;
196         }
197
198         for (String target : targets) {
199             List<String> targetNodeTemplateIds = componentDisplayNameToNodeTempalteIds.get(target);
200             if (CollectionUtils.isEmpty(targetNodeTemplateIds)) {
201                 continue;
202             }
203             for (String targetNodeTemplateId : targetNodeTemplateIds) {
204                 Optional<String> dependencyRequirementKey =
205                         getDependencyRequirementKey(serviceTemplate, componentDisplayName, nodeTemplate,
206                                 toscaServiceModel);
207                 if (dependencyRequirementKey.isPresent()) {
208                     RequirementAssignment requirementAssignment = new RequirementAssignment();
209                     requirementAssignment.setCapability(NATIVE_NODE);
210                     requirementAssignment.setRelationship(NATIVE_DEPENDS_ON);
211                     requirementAssignment.setNode(targetNodeTemplateId);
212                     DataModelUtil.addRequirementAssignment(nodeTemplate, dependencyRequirementKey.get(),
213                             requirementAssignment);
214                 }
215             }
216         }
217     }
218
219     private Optional<String> getDependencyRequirementKey(ServiceTemplate serviceTemplate, String componentDisplayName,
220                                                                 NodeTemplate nodeTemplate,
221                                                                 ToscaServiceModel toscaServiceModel) {
222         String nodeType = nodeTemplate.getType();
223         NodeType flatNodeType = (NodeType) toscaAnalyzerService.getFlatEntity(ToscaElementTypes.NODE_TYPE, nodeType,
224                 serviceTemplate, toscaServiceModel).getFlatEntity();
225         List<Map<String, RequirementDefinition>> flatNodeTypeRequirements = flatNodeType.getRequirements();
226         if (Objects.isNull(flatNodeTypeRequirements)) {
227             return Optional.empty();
228         }
229         for (Map<String, RequirementDefinition> requirementDefinitionMap : flatNodeTypeRequirements) {
230             String requirementKey = requirementDefinitionMap.keySet().iterator().next();
231             String expectedKey = ToscaConstants.DEPENDS_ON_REQUIREMENT_ID + "_" + componentDisplayName;
232             if (requirementKey.equals(expectedKey)) {
233                 return Optional.of(requirementKey);
234             }
235         }
236         return Optional.empty();
237     }
238
239     private String getComponentDisplayName(String nodeTemplateId, NodeTemplate nodeTemplate) {
240         String componentDisplayName;
241         if (nodeTemplateId.contains(ABSTRACT_NODE_TEMPLATE_ID_PREFIX)) {
242             String removedPrefix = nodeTemplateId.split(ABSTRACT_NODE_TEMPLATE_ID_PREFIX)[1];
243             final String[] removedSuffix = removedPrefix.split("_\\d");
244             componentDisplayName = removedSuffix[0];
245         } else {
246             final String type = nodeTemplate.getType();
247             componentDisplayName = MULTIDEPLOYMENTFLAVOR_NODE_TYPE.equals(type)
248                             ? nodeTemplateId.substring(0, nodeTemplateId.lastIndexOf(VNF_NODE_TEMPLATE_ID_SUFFIX))
249                             : type.substring(type.lastIndexOf('.') + 1);
250         }
251         return componentDisplayName;
252     }
253
254     private String getValueFromQuestionnaireDetails(Map<String, Map<String, Object>> componentTypetoParams,
255                                                            String componentDisplayName, String propertyName) {
256         return (String) componentTypetoParams.get(componentDisplayName).get(propertyName);
257     }
258
259     private void setProperty(NodeTemplate nodeTemplate, String key, String value) {
260         if (!StringUtils.isEmpty(value)) {
261             //YamlUtil throws IllegalStateException("duplicate key: " + key) if key is already present.
262             // So first removing and then populating same key with new updated value
263             nodeTemplate.getProperties().remove(key);
264             nodeTemplate.getProperties().put(key, value);
265         }
266     }
267
268     private Boolean getValue(String value) {
269         switch (value) {
270             case "YES":
271                 return true;
272             case "NO":
273                 return false;
274             default:
275                 return null;
276         }
277     }
278
279     private ComponentQuestionnaireData getComponentQuestionnaireData() {
280         if (componentQuestionnaireData == null) {
281             componentQuestionnaireData = new ComponentQuestionnaireData();
282         }
283         return componentQuestionnaireData;
284     }
285 }