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