02389d0b514414cae046ff81cac997754dc4d947
[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.types.LoggerConstants;
31 import org.openecomp.sdc.logging.types.LoggerErrorCode;
32 import org.openecomp.sdc.logging.types.LoggerErrorDescription;
33 import org.openecomp.sdc.logging.types.LoggerTragetServiceName;
34 import org.openecomp.sdc.tosca.datatypes.ToscaCapabilityType;
35 import org.openecomp.sdc.tosca.datatypes.ToscaNodeType;
36 import org.openecomp.sdc.tosca.datatypes.ToscaRelationshipType;
37 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
38 import org.openecomp.sdc.tosca.datatypes.model.NodeTemplate;
39 import org.openecomp.sdc.tosca.datatypes.model.NodeType;
40 import org.openecomp.sdc.tosca.datatypes.model.RequirementDefinition;
41 import org.openecomp.sdc.tosca.services.ToscaAnalyzerService;
42 import org.openecomp.sdc.tosca.services.impl.ToscaAnalyzerServiceImpl;
43 import org.openecomp.sdc.translator.datatypes.heattotosca.AttachedResourceId;
44 import org.openecomp.sdc.translator.datatypes.heattotosca.TranslationContext;
45 import org.openecomp.sdc.translator.datatypes.heattotosca.to.ResourceFileDataAndIDs;
46 import org.openecomp.sdc.translator.datatypes.heattotosca.to.TranslateTo;
47 import org.openecomp.sdc.translator.datatypes.heattotosca.to.TranslatedHeatResource;
48 import org.openecomp.sdc.translator.services.heattotosca.HeatToToscaUtil;
49 import org.openecomp.sdc.translator.services.heattotosca.errors.MissingMandatoryPropertyErrorBuilder;
50 import org.openecomp.sdc.translator.services.heattotosca.helper.VolumeTranslationHelper;
51
52 import java.util.ArrayList;
53 import java.util.Collections;
54 import java.util.List;
55 import java.util.Map;
56 import java.util.Objects;
57 import java.util.Optional;
58 import java.util.function.Predicate;
59 import java.util.stream.Collectors;
60
61 class NovaToVolResourceConnection extends ResourceConnectionUsingRequirementHelper {
62
63   public NovaToVolResourceConnection(ResourceTranslationBase resourceTranslationBase,
64                                      TranslateTo translateTo, FileData nestedFileData,
65                                      NodeTemplate substitutionNodeTemplate, NodeType nodeType) {
66     super(resourceTranslationBase, translateTo, nestedFileData, substitutionNodeTemplate, nodeType);
67   }
68
69   @Override
70   boolean isDesiredNodeTemplateType(NodeTemplate nodeTemplate) {
71     ToscaAnalyzerService toscaAnalyzerService = new ToscaAnalyzerServiceImpl();
72     ToscaServiceModel toscaServiceModel =
73         HeatToToscaUtil.getToscaServiceModel(translateTo.getContext());
74     return toscaAnalyzerService.isTypeOf(nodeTemplate, ToscaNodeType.NOVA_SERVER,
75         translateTo.getContext().getTranslatedServiceTemplates()
76             .get(translateTo.getResource().getType()), toscaServiceModel);
77   }
78
79   @Override
80   List<Predicate<RequirementDefinition>> getPredicatesListForConnectionPoints() {
81     ArrayList<Predicate<RequirementDefinition>> predicates = new ArrayList<>();
82     predicates
83         .add(req -> req.getCapability().equals(ToscaCapabilityType.NATIVE_ATTACHMENT)
84             && req.getNode().equals(ToscaNodeType.NATIVE_BLOCK_STORAGE)
85             && req.getRelationship()
86             .equals(ToscaRelationshipType.NATIVE_ATTACHES_TO));
87     return predicates;
88   }
89
90   @Override
91   Optional<List<String>> getConnectorPropertyParamName(String heatResourceId, Resource heatResource,
92                                                        HeatOrchestrationTemplate
93                                                            nestedHeatOrchestrationTemplate,
94                                                        String nestedHeatFileName) {
95
96
97
98     Optional<AttachedResourceId> volumeId = HeatToToscaUtil
99         .extractAttachedResourceId(nestedFileData.getFile(), nestedHeatOrchestrationTemplate,
100             translateTo.getContext(), heatResource.getProperties().get("volume_id"));
101     if (volumeId.isPresent() && volumeId.get().isGetParam()
102         && volumeId.get().getEntityId() instanceof String) {
103       return Optional.of(Collections.singletonList((String) volumeId.get().getEntityId()));
104     } else {
105       return Optional.empty();
106     }
107   }
108
109   @Override
110   String getDesiredResourceType() {
111     return HeatResourcesTypes.CINDER_VOLUME_ATTACHMENT_RESOURCE_TYPE.getHeatResource();
112   }
113
114   @Override
115   void addRequirementToConnectResources(
116       Map.Entry<String, RequirementDefinition> requirementDefinitionEntry,
117       List<String> paramNames) {
118
119
120
121     if (paramNames == null || paramNames.isEmpty()) {
122       return;
123     }
124
125     List<String> supportedVolumeTypes =
126         Collections.singletonList(HeatResourcesTypes.CINDER_VOLUME_RESOURCE_TYPE.getHeatResource());
127
128     for (String paramName : paramNames) {
129       Object paramValue = translateTo.getResource().getProperties().get(paramName);
130       addRequirementToConnectResource(requirementDefinitionEntry, paramName, paramValue,
131           supportedVolumeTypes);
132     }
133
134   }
135
136   @Override
137   boolean validateResourceTypeSupportedForReqCreation(String nestedResourceId,
138                                                       String nestedPropertyName,
139                                                       String connectionPointId,
140                                                       Resource connectedResource,
141                                                       List<String> supportedTypes) {
142
143
144
145     if (!resourceTranslationBase.isResourceTypeSupported(connectedResource, supportedTypes)) {
146       logger.warn("Nested resource '" + nestedResourceId + "' property '" + nestedPropertyName
147           + "' is pointing to a resource with type '" + connectedResource.getType()
148           + "' which is not supported for requirement '" + connectionPointId
149           + "' that connect VolumeAttachment to Volume. Supported types are: '"
150           + supportedTypes.toString()
151           + "', therefore, this TOSCA requirement will not be connected.");
152
153       return false;
154     }
155
156     return true;
157   }
158
159   @Override
160   protected Optional<List<Map.Entry<String, Resource>>> getResourceByTranslatedResourceId(
161       String translatedResourceId, HeatOrchestrationTemplate nestedHeatOrchestrationTemplate) {
162
163
164
165     List<Predicate<Map.Entry<String, Resource>>> predicates =
166         buildPredicates(nestedFileData.getFile(), nestedHeatOrchestrationTemplate,
167             translatedResourceId);
168     List<Map.Entry<String, Resource>> list =
169         nestedHeatOrchestrationTemplate.getResources().entrySet()
170             .stream()
171             .filter(entry -> predicates
172                 .stream()
173                     .allMatch(p -> p.test(entry)))
174             .collect(Collectors.toList());
175     if (CollectionUtils.isEmpty(list)) {
176       return Optional.empty();
177     } else {
178       return Optional.of(list);
179     }
180   }
181
182   @Override
183   Optional<String> getConnectionTranslatedNodeUsingGetParamFunc(
184       Map.Entry<String, RequirementDefinition> requirementDefinitionEntry, String paramName,
185       List<String> supportedTargetNodeTypes) {
186
187
188
189     Optional<String> targetTranslatedNodeId = super
190         .getConnectionTranslatedNodeUsingGetParamFunc(requirementDefinitionEntry, paramName,
191             supportedTargetNodeTypes);
192     if (targetTranslatedNodeId.isPresent()) {
193       return targetTranslatedNodeId;
194     } else {
195       Optional<AttachedResourceId> attachedResourceId =
196           HeatToToscaUtil.extractAttachedResourceId(translateTo, paramName);
197       if (!attachedResourceId.isPresent()) {
198         return Optional.empty();
199       }
200       AttachedResourceId resourceId = attachedResourceId.get();
201       if (resourceId.isGetParam() && resourceId.getEntityId() instanceof String) {
202         TranslatedHeatResource shareResource =
203             translateTo.getContext().getHeatSharedResourcesByParam().get(resourceId.getEntityId());
204         if (Objects.isNull(shareResource)) {
205           List<FileData> allFilesData =
206               translateTo.getContext().getManifest().getContent().getData();
207           Optional<FileData> fileData =
208               HeatToToscaUtil.getFileData(translateTo.getHeatFileName(), allFilesData);
209           if (fileData.isPresent()) {
210             Optional<ResourceFileDataAndIDs> fileDataContainingResource =
211                 new VolumeTranslationHelper(logger)
212                     .getFileDataContainingVolume(fileData.get().getData(),
213                         (String) resourceId.getEntityId(), translateTo, FileData.Type.HEAT_VOL);
214             if (fileDataContainingResource.isPresent()) {
215               return Optional.of(fileDataContainingResource.get().getTranslatedResourceId());
216             }
217           }
218         }
219       }
220
221       return Optional.empty();
222     }
223   }
224
225   private List<Predicate<Map.Entry<String, Resource>>> buildPredicates(
226       String fileName,
227       HeatOrchestrationTemplate heatOrchestrationTemplate,
228       String novaTranslatedResourceId) {
229     List<Predicate<Map.Entry<String, Resource>>> list = new ArrayList<>();
230     list.add(entry -> entry.getValue().getType().equals(getDesiredResourceType()));
231     list.add(entry -> {
232       Object instanceUuidProp = entry.getValue().getProperties().get("instance_uuid");
233       TranslationContext context = translateTo.getContext();
234       Optional<AttachedResourceId> instanceUuid = HeatToToscaUtil
235           .extractAttachedResourceId(fileName, heatOrchestrationTemplate, context,
236               instanceUuidProp);
237       if (instanceUuid.isPresent()) {
238         Optional<String> resourceTranslatedId =
239             ResourceTranslationBase.getResourceTranslatedId(fileName, heatOrchestrationTemplate,
240                 (String) instanceUuid.get().getTranslatedId(), context);
241         return resourceTranslatedId.isPresent()
242             && resourceTranslatedId.get().equals(novaTranslatedResourceId);
243
244       } else {
245         throw new CoreException(new MissingMandatoryPropertyErrorBuilder("instance_uuid").build());
246       }
247     });
248     return list;
249   }
250 }