623eeca66beae24e01dd70f557c1bf25a70e16d1
[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.lang3.StringUtils;
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.HeatResourcesTypes;
28 import org.openecomp.sdc.heat.datatypes.model.Resource;
29 import org.openecomp.sdc.heat.services.HeatConstants;
30 import org.openecomp.sdc.logging.api.Logger;
31 import org.openecomp.sdc.logging.api.LoggerFactory;
32 import org.openecomp.sdc.logging.types.LoggerConstants;
33 import org.openecomp.sdc.logging.types.LoggerErrorCode;
34 import org.openecomp.sdc.logging.types.LoggerErrorDescription;
35 import org.openecomp.sdc.logging.types.LoggerTragetServiceName;
36 import org.openecomp.sdc.tosca.datatypes.ToscaRelationshipType;
37 import org.openecomp.sdc.tosca.datatypes.ToscaTopologyTemplateElements;
38 import org.openecomp.sdc.tosca.datatypes.model.NodeTemplate;
39 import org.openecomp.sdc.tosca.datatypes.model.RelationshipTemplate;
40 import org.openecomp.sdc.tosca.datatypes.model.RequirementAssignment;
41 import org.openecomp.sdc.tosca.services.DataModelUtil;
42 import org.openecomp.sdc.tosca.services.ToscaConstants;
43 import org.openecomp.sdc.translator.datatypes.heattotosca.AttachedResourceId;
44 import org.openecomp.sdc.translator.datatypes.heattotosca.to.ResourceFileDataAndIDs;
45 import org.openecomp.sdc.translator.datatypes.heattotosca.to.TranslateTo;
46 import org.openecomp.sdc.translator.services.heattotosca.ConsolidationDataUtil;
47 import org.openecomp.sdc.translator.services.heattotosca.HeatToToscaUtil;
48 import org.openecomp.sdc.translator.services.heattotosca.ResourceTranslationFactory;
49 import org.openecomp.sdc.translator.services.heattotosca.errors.MissingMandatoryPropertyErrorBuilder;
50 import org.openecomp.sdc.translator.services.heattotosca.helper.VolumeTranslationHelper;
51 import org.openecomp.sdc.translator.services.heattotosca.mapping.TranslatorHeatToToscaPropertyConverter;
52
53 import java.util.List;
54 import java.util.Optional;
55
56 import static org.openecomp.sdc.translator.services.heattotosca.HeatToToscaUtil.getResource;
57
58 public class ResourceTranslationCinderVolumeAttachmentImpl extends ResourceTranslationBase {
59   protected static Logger logger =
60       (Logger) LoggerFactory.getLogger(ResourceTranslationCinderVolumeAttachmentImpl.class);
61   private String volumeIdPropertyName = "volume_id";
62   private String toscaCapabilityAttachment = "tosca.capabilities.Attachment";
63
64   @Override
65   protected void translate(TranslateTo translateTo) {
66     RelationshipTemplate relationTemplate = new RelationshipTemplate();
67     relationTemplate.setType(ToscaRelationshipType.CINDER_VOLUME_ATTACHES_TO);
68     String relationshipTemplateId = translateTo.getTranslatedId();
69     String heatFileName = translateTo.getHeatFileName();
70     relationTemplate.setProperties(TranslatorHeatToToscaPropertyConverter
71         .getToscaPropertiesSimpleConversion(translateTo.getServiceTemplate(),translateTo
72             .getResourceId(),translateTo.getResource().getProperties(),
73             relationTemplate.getProperties(), heatFileName,
74             translateTo.getHeatOrchestrationTemplate(), translateTo.getResource().getType(),
75             relationTemplate, translateTo.getContext()));
76
77     AttachedResourceId attachedVolumeId = getAttachedResourceId(translateTo, volumeIdPropertyName);
78     String instanceUuid = HeatConstants.INSTANCE_UUID_PROPERTY_NAME;
79     AttachedResourceId attachedNovaServerId = getAttachedResourceId(translateTo, instanceUuid);
80
81     if (attachedNovaServerId.isGetResource()) {
82       handleNovaGetResource(translateTo, relationTemplate, relationshipTemplateId, heatFileName,
83           attachedVolumeId, (String) attachedNovaServerId.getEntityId());
84     } else {
85       logger.warn("Heat resource: '" + translateTo.getResourceId() + "' with type: '"
86           + translateTo.getResource().getType()
87           + "' include 'instance_uuid' property without 'get_resource' function, therefore this "
88           + "resource will be ignored in TOSCA translation.");
89     }
90   }
91
92   @Override
93   protected Optional<ToscaTopologyTemplateElements> getTranslatedToscaTopologyElement(
94       TranslateTo translateTo) {
95     if (isEssentialRequirementsValid(translateTo)) {
96       return Optional.of(ToscaTopologyTemplateElements.RELATIONSHIP_TEMPLATE);
97     } else {
98       return Optional.empty();
99     }
100   }
101
102   private AttachedResourceId getAttachedResourceId(TranslateTo translateTo, String propertyName) {
103     Optional<AttachedResourceId> attachedResourceId =
104         HeatToToscaUtil.extractAttachedResourceId(translateTo, propertyName);
105     if (!attachedResourceId.isPresent()) {
106       throw new CoreException(new MissingMandatoryPropertyErrorBuilder(propertyName).build());
107     }
108     return attachedResourceId.get();
109   }
110
111   private void handleNovaGetResource(TranslateTo translateTo, RelationshipTemplate relationTemplate,
112                                      String relationshipTemplateId, String heatFileName,
113                                      AttachedResourceId volResourceId, String novaResourceId) {
114     RequirementAssignment requirement = new RequirementAssignment();
115     requirement.setCapability(toscaCapabilityAttachment);
116     if (volResourceId.isGetResource()) {
117       Resource volServerResource = getResource(translateTo.getHeatOrchestrationTemplate(),
118           (String) volResourceId.getTranslatedId(), heatFileName);
119       if (!StringUtils.equals(HeatResourcesTypes.CINDER_VOLUME_RESOURCE_TYPE.getHeatResource(),
120           volServerResource.getType())) {
121         logger.warn("Volume attachment with id '" + translateTo.getResourceId()
122             + "' is pointing to unsupported resource type(" + volServerResource.getType()
123             + ") through the property 'volume_id'."
124             + " The connection to the volume is ignored. "
125             + "Supported types are: "
126             + HeatResourcesTypes.CINDER_VOLUME_RESOURCE_TYPE.getHeatResource());
127         return;
128       }
129       requirement.setNode((String) volResourceId.getTranslatedId());
130       requirement.setRelationship(relationshipTemplateId);
131       DataModelUtil
132           .addRelationshipTemplate(translateTo.getServiceTemplate(), relationshipTemplateId,
133               relationTemplate);
134     } else if (volResourceId.isGetParam() && volResourceId.getEntityId() instanceof String) {
135       String volumeResourceIdParamName = (String) volResourceId.getEntityId();
136       if (translateTo.getContext().getHeatSharedResourcesByParam()
137           .containsKey(volumeResourceIdParamName) && !isHeatFileNested(translateTo, heatFileName)) {
138         Resource volServerResource =
139             translateTo.getContext().getHeatSharedResourcesByParam().get(volumeResourceIdParamName)
140                 .getHeatResource();
141         if (!StringUtils.equals(HeatResourcesTypes.CINDER_VOLUME_RESOURCE_TYPE.getHeatResource(),
142             volServerResource.getType())) {
143           logger.warn("Volume attachment with id '" + translateTo.getResourceId()
144               + "' is pointing to unsupported resource type(" + volServerResource.getType()
145               + ") through the property 'volume_id'."
146               + " The connection to the volume is ignored. "
147               + "Supported types are: "
148               + HeatResourcesTypes.CINDER_VOLUME_RESOURCE_TYPE.getHeatResource());
149           return;
150         }
151         requirement.setNode(
152             translateTo.getContext().getHeatSharedResourcesByParam().get(volumeResourceIdParamName)
153                 .getTranslatedId());
154         requirement.setRelationship(relationshipTemplateId);
155         DataModelUtil
156             .addRelationshipTemplate(translateTo.getServiceTemplate(), relationshipTemplateId,
157                 relationTemplate);
158       } else {
159         handleUnsharedVolume(translateTo, relationTemplate, relationshipTemplateId, heatFileName,
160             requirement, volumeResourceIdParamName);
161       }
162     }
163     Resource novaServerResource =
164         getResource(translateTo.getHeatOrchestrationTemplate(), novaResourceId, heatFileName);
165     if (!StringUtils.equals(HeatResourcesTypes.NOVA_SERVER_RESOURCE_TYPE.getHeatResource(),
166         novaServerResource.getType())) {
167       logger.warn("Volume attachment with id '" + translateTo.getResourceId()
168           + "' is pointing to unsupported resource type(" + novaServerResource.getType()
169           + ") through the property 'instance_uuid'."
170           + " The connection to the nova server is ignored. "
171           + "Supported types are: "
172           + HeatResourcesTypes.NOVA_SERVER_RESOURCE_TYPE.getHeatResource());
173       return;
174     }
175     Optional<String> translatedNovaServerId =
176         ResourceTranslationFactory.getInstance(novaServerResource)
177             .translateResource(heatFileName, translateTo.getServiceTemplate(),
178                 translateTo.getHeatOrchestrationTemplate(), novaServerResource, novaResourceId,
179                 translateTo.getContext());
180
181     if (translatedNovaServerId.isPresent() && StringUtils.isNotEmpty(requirement.getNode())) {
182       NodeTemplate novaServerNodeTemplate = DataModelUtil
183           .getNodeTemplate(translateTo.getServiceTemplate(), translatedNovaServerId.get());
184       DataModelUtil.addRequirementAssignment(novaServerNodeTemplate, ToscaConstants
185           .LOCAL_STORAGE_REQUIREMENT_ID, requirement);
186       //Add volume information to consolidation data
187       ConsolidationDataUtil.updateComputeConsolidationDataVolumes(translateTo,
188           novaServerNodeTemplate.getType(), translatedNovaServerId.get(), ToscaConstants
189           .LOCAL_STORAGE_REQUIREMENT_ID, requirement);
190     }
191   }
192
193   private void handleUnsharedVolume(TranslateTo translateTo, RelationshipTemplate relationTemplate,
194                                     String relationshipTemplateId, String heatFileName,
195                                     RequirementAssignment requirement, String volumeResourceId) {
196     List<FileData> allFilesData = translateTo.getContext().getManifest().getContent().getData();
197     Optional<FileData> fileData = HeatToToscaUtil.getFileData(heatFileName, allFilesData);
198     if (fileData.isPresent()) {
199       Optional<ResourceFileDataAndIDs> fileDataContainingResource =
200           new VolumeTranslationHelper(logger)
201               .getFileDataContainingVolume(fileData.get().getData(), volumeResourceId, translateTo,
202                   FileData.Type.HEAT_VOL);
203       fileDataContainingResource.ifPresent(
204           resourceFileDataAndIDs -> addRelationshipToServiceTemplate(translateTo, relationTemplate,
205               relationshipTemplateId, requirement, resourceFileDataAndIDs));
206     }
207   }
208
209   private boolean isHeatFileNested(TranslateTo translateTo, String heatFileName) {
210     return translateTo.getContext().getNestedHeatsFiles().contains(heatFileName);
211   }
212
213   private void addRelationshipToServiceTemplate(TranslateTo translateTo,
214                                                 RelationshipTemplate relationTemplate,
215                                                 String relationshipTemplateId,
216                                                 RequirementAssignment requirement,
217                                                 ResourceFileDataAndIDs resourceFileDataAndIDs) {
218     String translatedId = resourceFileDataAndIDs.getTranslatedResourceId();
219     String toscaVolIdPropName =
220         HeatToToscaUtil.getToscaPropertyName(translateTo, HeatConstants.VOL_ID_PROPERTY_NAME);
221     relationTemplate.getProperties().put(toscaVolIdPropName, translatedId);
222     requirement.setNode(translatedId);
223     requirement.setRelationship(relationshipTemplateId);
224     DataModelUtil.addRelationshipTemplate(translateTo.getServiceTemplate(), relationshipTemplateId,
225         relationTemplate);
226   }
227 }