f1b64a195cb4f9667d2f54c56f80faa35eadba0c
[sdc.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.sdc.translator.services.heattotosca.impl.resourcetranslation;
22
23 import org.apache.commons.collections4.CollectionUtils;
24 import org.openecomp.sdc.common.errors.CoreException;
25 import org.openecomp.sdc.datatypes.error.ErrorLevel;
26 import org.openecomp.sdc.heat.datatypes.manifest.FileData;
27 import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate;
28 import org.openecomp.sdc.heat.datatypes.model.HeatResourcesTypes;
29 import org.openecomp.sdc.heat.datatypes.model.Resource;
30 import org.openecomp.sdc.logging.context.impl.MdcDataErrorMessage;
31 import org.openecomp.sdc.logging.types.LoggerConstants;
32 import org.openecomp.sdc.logging.types.LoggerErrorCode;
33 import org.openecomp.sdc.logging.types.LoggerErrorDescription;
34 import org.openecomp.sdc.logging.types.LoggerTragetServiceName;
35 import org.openecomp.sdc.tosca.datatypes.ToscaCapabilityType;
36 import org.openecomp.sdc.tosca.datatypes.ToscaNodeType;
37 import org.openecomp.sdc.tosca.datatypes.ToscaRelationshipType;
38 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
39 import org.openecomp.sdc.tosca.datatypes.model.NodeTemplate;
40 import org.openecomp.sdc.tosca.datatypes.model.NodeType;
41 import org.openecomp.sdc.tosca.datatypes.model.RequirementDefinition;
42 import org.openecomp.sdc.tosca.services.ToscaAnalyzerService;
43 import org.openecomp.sdc.tosca.services.impl.ToscaAnalyzerServiceImpl;
44 import org.openecomp.sdc.translator.datatypes.heattotosca.AttachedResourceId;
45 import org.openecomp.sdc.translator.datatypes.heattotosca.TranslationContext;
46 import org.openecomp.sdc.translator.datatypes.heattotosca.to.ResourceFileDataAndIDs;
47 import org.openecomp.sdc.translator.datatypes.heattotosca.to.TranslateTo;
48 import org.openecomp.sdc.translator.datatypes.heattotosca.to.TranslatedHeatResource;
49 import org.openecomp.sdc.translator.services.heattotosca.HeatToToscaUtil;
50 import org.openecomp.sdc.translator.services.heattotosca.errors.MissingMandatoryPropertyErrorBuilder;
51 import org.openecomp.sdc.translator.services.heattotosca.helper.VolumeTranslationHelper;
52
53 import java.util.ArrayList;
54 import java.util.Collections;
55 import java.util.List;
56 import java.util.Map;
57 import java.util.Objects;
58 import java.util.Optional;
59 import java.util.function.Predicate;
60 import java.util.stream.Collectors;
61
62 class NovaToVolResourceConnection extends ResourceConnectionUsingRequirementHelper {
63
64   public NovaToVolResourceConnection(ResourceTranslationBase resourceTranslationBase,
65                                      TranslateTo translateTo, FileData nestedFileData,
66                                      NodeTemplate substitutionNodeTemplate, NodeType nodeType) {
67     super(resourceTranslationBase, translateTo, nestedFileData, substitutionNodeTemplate, nodeType);
68   }
69
70   @Override
71   boolean isDesiredNodeTemplateType(NodeTemplate nodeTemplate) {
72     ToscaAnalyzerService toscaAnalyzerService = new ToscaAnalyzerServiceImpl();
73     ToscaServiceModel toscaServiceModel =
74         HeatToToscaUtil.getToscaServiceModel(translateTo.getContext());
75     return toscaAnalyzerService.isTypeOf(nodeTemplate, ToscaNodeType.NOVA_SERVER,
76         translateTo.getContext().getTranslatedServiceTemplates()
77             .get(translateTo.getResource().getType()), toscaServiceModel);
78   }
79
80   @Override
81   List<Predicate<RequirementDefinition>> getPredicatesListForConnectionPoints() {
82     ArrayList<Predicate<RequirementDefinition>> predicates = new ArrayList<>();
83     predicates
84         .add(req -> req.getCapability().equals(ToscaCapabilityType.NATIVE_ATTACHMENT)
85             && req.getNode().equals(ToscaNodeType.NATIVE_BLOCK_STORAGE)
86             && req.getRelationship()
87             .equals(ToscaRelationshipType.NATIVE_ATTACHES_TO));
88     return predicates;
89   }
90
91   @Override
92   Optional<List<String>> getConnectorPropertyParamName(String heatResourceId, Resource heatResource,
93                                                        HeatOrchestrationTemplate
94                                                            nestedHeatOrchestrationTemplate,
95                                                        String nestedHeatFileName) {
96
97
98
99     Optional<AttachedResourceId> volumeId = HeatToToscaUtil
100         .extractAttachedResourceId(nestedFileData.getFile(), nestedHeatOrchestrationTemplate,
101             translateTo.getContext(), heatResource.getProperties().get("volume_id"));
102     if (volumeId.isPresent() && volumeId.get().isGetParam()
103         && volumeId.get().getEntityId() instanceof String) {
104       return Optional.of(Collections.singletonList((String) volumeId.get().getEntityId()));
105     } else {
106       return Optional.empty();
107     }
108   }
109
110   @Override
111   String getDesiredResourceType() {
112     return HeatResourcesTypes.CINDER_VOLUME_ATTACHMENT_RESOURCE_TYPE.getHeatResource();
113   }
114
115   @Override
116   void addRequirementToConnectResources(
117       Map.Entry<String, RequirementDefinition> requirementDefinitionEntry,
118       List<String> paramNames) {
119
120
121
122     if (paramNames == null || paramNames.isEmpty()) {
123       return;
124     }
125
126     List<String> supportedVolumeTypes =
127         Collections.singletonList(HeatResourcesTypes.CINDER_VOLUME_RESOURCE_TYPE.getHeatResource());
128
129     for (String paramName : paramNames) {
130       Object paramValue = translateTo.getResource().getProperties().get(paramName);
131       addRequirementToConnectResource(requirementDefinitionEntry, paramName, paramValue,
132           supportedVolumeTypes);
133     }
134
135   }
136
137   @Override
138   boolean validateResourceTypeSupportedForReqCreation(String nestedResourceId,
139                                                       String nestedPropertyName,
140                                                       String connectionPointId,
141                                                       Resource connectedResource,
142                                                       List<String> supportedTypes) {
143
144
145
146     if (!resourceTranslationBase.isResourceTypeSupported(connectedResource, supportedTypes)) {
147       logger.warn("Nested resource '" + nestedResourceId + "' property '" + nestedPropertyName
148           + "' is pointing to a resource with type '" + connectedResource.getType()
149           + "' which is not supported for requirement '" + connectionPointId
150           + "' that connect VolumeAttachment to Volume. Supported types are: '"
151           + supportedTypes.toString()
152           + "', therefore, this TOSCA requirement will not be connected.");
153
154       return false;
155     }
156
157     return true;
158   }
159
160   @Override
161   protected Optional<List<Map.Entry<String, Resource>>> getResourceByTranslatedResourceId(
162       String translatedResourceId, HeatOrchestrationTemplate nestedHeatOrchestrationTemplate) {
163
164
165
166     List<Predicate<Map.Entry<String, Resource>>> predicates =
167         buildPredicates(nestedFileData.getFile(), nestedHeatOrchestrationTemplate,
168             translatedResourceId);
169     List<Map.Entry<String, Resource>> list =
170         nestedHeatOrchestrationTemplate.getResources().entrySet()
171             .stream()
172             .filter(entry -> predicates
173                 .stream()
174                     .allMatch(p -> p.test(entry)))
175             .collect(Collectors.toList());
176     if (CollectionUtils.isEmpty(list)) {
177       return Optional.empty();
178     } else {
179       return Optional.of(list);
180     }
181   }
182
183   @Override
184   Optional<String> getConnectionTranslatedNodeUsingGetParamFunc(
185       Map.Entry<String, RequirementDefinition> requirementDefinitionEntry, String paramName,
186       List<String> supportedTargetNodeTypes) {
187
188
189
190     Optional<String> targetTranslatedNodeId = super
191         .getConnectionTranslatedNodeUsingGetParamFunc(requirementDefinitionEntry, paramName,
192             supportedTargetNodeTypes);
193     if (targetTranslatedNodeId.isPresent()) {
194       return targetTranslatedNodeId;
195     } else {
196       Optional<AttachedResourceId> attachedResourceId =
197           HeatToToscaUtil.extractAttachedResourceId(translateTo, paramName);
198       if (!attachedResourceId.isPresent()) {
199         return Optional.empty();
200       }
201       AttachedResourceId resourceId = attachedResourceId.get();
202       if (resourceId.isGetParam() && resourceId.getEntityId() instanceof String) {
203         TranslatedHeatResource shareResource =
204             translateTo.getContext().getHeatSharedResourcesByParam().get(resourceId.getEntityId());
205         if (Objects.isNull(shareResource)) {
206           List<FileData> allFilesData =
207               translateTo.getContext().getManifest().getContent().getData();
208           Optional<FileData> fileData =
209               HeatToToscaUtil.getFileData(translateTo.getHeatFileName(), allFilesData);
210           if (fileData.isPresent()) {
211             Optional<ResourceFileDataAndIDs> fileDataContainingResource =
212                 new VolumeTranslationHelper(logger)
213                     .getFileDataContainingVolume(fileData.get().getData(),
214                         (String) resourceId.getEntityId(), translateTo, FileData.Type.HEAT_VOL);
215             if (fileDataContainingResource.isPresent()) {
216               return Optional.of(fileDataContainingResource.get().getTranslatedResourceId());
217             }
218           }
219         }
220       }
221
222       return Optional.empty();
223     }
224   }
225
226   private List<Predicate<Map.Entry<String, Resource>>> buildPredicates(
227       String fileName,
228       HeatOrchestrationTemplate heatOrchestrationTemplate,
229       String novaTranslatedResourceId) {
230     List<Predicate<Map.Entry<String, Resource>>> list = new ArrayList<>();
231     list.add(entry -> entry.getValue().getType().equals(getDesiredResourceType()));
232     list.add(entry -> {
233       Object instanceUuidProp = entry.getValue().getProperties().get("instance_uuid");
234       TranslationContext context = translateTo.getContext();
235       Optional<AttachedResourceId> instanceUuid = HeatToToscaUtil
236           .extractAttachedResourceId(fileName, heatOrchestrationTemplate, context,
237               instanceUuidProp);
238       if (instanceUuid.isPresent()) {
239         Optional<String> resourceTranslatedId =
240             ResourceTranslationBase.getResourceTranslatedId(fileName, heatOrchestrationTemplate,
241                 (String) instanceUuid.get().getTranslatedId(), context);
242         return resourceTranslatedId.isPresent()
243             && resourceTranslatedId.get().equals(novaTranslatedResourceId);
244
245       } else {
246         MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
247             LoggerTragetServiceName.GET_RESOURCE, ErrorLevel.ERROR.name(),
248             LoggerErrorCode.DATA_ERROR.getErrorCode(),
249             LoggerErrorDescription.MISSING_MANDATORY_PROPERTY);
250         throw new CoreException(new MissingMandatoryPropertyErrorBuilder("instance_uuid").build());
251       }
252     });
253     return list;
254   }
255 }