2 * Copyright © 2018 European Support Limited
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package org.openecomp.sdc.healing.healers;
19 import com.amdocs.zusammen.adaptor.inbound.api.types.item.Element;
20 import com.amdocs.zusammen.adaptor.inbound.api.types.item.ElementInfo;
21 import com.amdocs.zusammen.adaptor.inbound.api.types.item.ZusammenElement;
22 import com.amdocs.zusammen.datatypes.Id;
23 import com.amdocs.zusammen.datatypes.SessionContext;
24 import com.amdocs.zusammen.datatypes.item.Action;
25 import com.amdocs.zusammen.datatypes.item.ElementContext;
26 import com.amdocs.zusammen.utils.fileutils.FileUtils;
27 import org.apache.commons.io.IOUtils;
28 import org.apache.commons.lang.ArrayUtils;
29 import org.apache.commons.lang.StringUtils;
30 import org.openecomp.core.utilities.file.FileContentHandler;
31 import org.openecomp.core.utilities.orchestration.OnboardingTypesEnum;
32 import org.openecomp.core.zusammen.api.ZusammenAdaptor;
33 import org.openecomp.core.zusammen.api.ZusammenAdaptorFactory;
34 import org.openecomp.sdc.common.errors.CoreException;
35 import org.openecomp.sdc.common.errors.ErrorCode;
36 import org.openecomp.sdc.common.utils.CommonUtil;
37 import org.openecomp.sdc.datatypes.error.ErrorLevel;
38 import org.openecomp.sdc.datatypes.model.ElementType;
39 import org.openecomp.sdc.healing.interfaces.Healer;
40 import org.openecomp.sdc.vendorsoftwareproduct.dao.VendorSoftwareProductInfoDao;
41 import org.openecomp.sdc.vendorsoftwareproduct.dao.VendorSoftwareProductInfoDaoFactory;
42 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.OnboardingMethod;
43 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.OrchestrationTemplateCandidateData;
44 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.OrchestrationTemplateEntity;
45 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails;
46 import org.openecomp.sdc.vendorsoftwareproduct.factory.CandidateServiceFactory;
47 import org.openecomp.sdc.vendorsoftwareproduct.services.filedatastructuremodule.CandidateService;
48 import org.openecomp.sdc.vendorsoftwareproduct.services.utils.CandidateEntityBuilder;
49 import org.openecomp.sdc.versioning.dao.types.Version;
51 import java.io.ByteArrayInputStream;
52 import java.io.IOException;
53 import java.io.InputStream;
54 import java.nio.ByteBuffer;
55 import java.util.Collection;
56 import java.util.Objects;
58 import static org.openecomp.core.zusammen.api.ZusammenUtil.*;
60 public class NetworkPackageHealer implements Healer {
62 private static final byte[] EMPTY_DATA_BYTES = "{}".getBytes();
63 private static final String MISSING_ORCHESTRATION_TEMPLATE_CANDIDATE_ERROR =
64 "Vsp with invalid structure: does not contain element OrchestrationTemplateCandidate";
65 private static final String MISSING_ORCHESTRATION_TEMPLATE_CANDIDATE_CONTENT_ERROR =
66 "Vsp with invalid structure: does not contain element OrchestrationTemplateCandidateContent"
67 + " under OrchestrationTemplateCandidate";
69 private static final String MISSING_VSP_MODEL_ERROR =
70 "Vsp with invalid structure: does not contain element VspModel";
71 private static final String MISSING_ORCHESTRATION_TEMPLATE_ERROR =
72 "Vsp with invalid structure: does not contain element OrchestrationTemplate"
73 + " under VspModel element";
74 private static final String MISSING_ORCHESTRATION_TEMPLATE_VALIDATE_DATA_ERROR =
75 "Vsp with invalid structure: does not contain element OrchestrationTemplateValidationData"
76 + " under OrchestrationTemplate element";
78 private final VendorSoftwareProductInfoDao vspInfoDao;
79 private final ZusammenAdaptor zusammenAdaptor;
80 private final CandidateService candidateService;
82 public NetworkPackageHealer() {
83 this(VendorSoftwareProductInfoDaoFactory.getInstance().createInterface(),
84 ZusammenAdaptorFactory.getInstance().createInterface(), CandidateServiceFactory
85 .getInstance().createInterface());
88 public NetworkPackageHealer(VendorSoftwareProductInfoDao vspInfoDao,
89 ZusammenAdaptor zusammenAdaptor,
90 CandidateService candidateService) {
91 this.vspInfoDao = vspInfoDao;
92 this.zusammenAdaptor = zusammenAdaptor;
93 this.candidateService = candidateService;
97 public boolean isHealingNeeded(String itemId, Version version) {
98 return OnboardingMethod.NetworkPackage.name()
99 .equals(vspInfoDao.get(new VspDetails(itemId, version)).getOnboardingMethod()) &&
100 isVspMissingAddedElements(itemId, version);
104 public void heal(String itemId, Version version) throws Exception {
105 SessionContext context = createSessionContext();
106 ElementContext elementContext = new ElementContext(itemId, version.getId());
108 Element candidateElement =
109 getElement(context, elementContext, null, ElementType.OrchestrationTemplateCandidate,
110 MISSING_ORCHESTRATION_TEMPLATE_CANDIDATE_ERROR);
112 Collection<Element> candidateSubs =
113 zusammenAdaptor.listElementData(context, elementContext, candidateElement.getElementId());
115 Id candidateValidationElementId =
116 creatIfAbsentCandidateValidationElementId(candidateSubs, context,
117 elementContext, candidateElement);
119 Element orchestrationTemplateElement = getOrchestrationTemplateElement(context, elementContext);
121 Collection<Element> orchestrationTemplateSubs = zusammenAdaptor
122 .listElementData(context, elementContext, orchestrationTemplateElement.getElementId());
124 Id structureElementId = createIfAbsentStructureElementId(orchestrationTemplateSubs, context,
125 elementContext, orchestrationTemplateElement);
127 Element orchestrationTemplateValidationElement = getOrchestrationTemplateValidationElement
128 (orchestrationTemplateSubs);
130 OrchestrationTemplateEntity orchestrationTemplateEntity =
131 getOrchestrationTemplateEntity(orchestrationTemplateElement,
132 orchestrationTemplateValidationElement);
134 if (StringUtils.isEmpty(orchestrationTemplateEntity.getFileSuffix())) {
138 Element candidateContentElement = getCandidateContentElement(candidateSubs);
140 VspDetails vspDetails = vspInfoDao.get(new VspDetails(itemId, version));
141 if (isEqual(orchestrationTemplateEntity,
142 getCandidateData(candidateElement, candidateContentElement))) {
144 if (isProcessedEntityValid(orchestrationTemplateEntity)) {
145 emptyStructureElementAndSub(context, elementContext, candidateElement.getElementId(),
146 ElementType.OrchestrationTemplateCandidate, candidateContentElement.getElementId(),
147 ElementType.OrchestrationTemplateCandidateContent);
149 populateOrchestrationTemplateStructure(orchestrationTemplateElement.getData(),
150 structureElementId, vspDetails, context, elementContext);
152 emptyStructureElementAndSub(context, elementContext,
153 orchestrationTemplateElement.getElementId(), ElementType.OrchestrationTemplate,
154 orchestrationTemplateValidationElement.getElementId(),
155 ElementType.OrchestrationTemplateValidationData);
157 populateCandidateValidationData(context, elementContext, candidateValidationElementId,
158 orchestrationTemplateEntity.getValidationData());
161 populateOrchestrationTemplateStructure(orchestrationTemplateElement.getData(),
162 structureElementId, vspDetails, context, elementContext);
166 private boolean isVspMissingAddedElements(String vspId, Version version) {
167 SessionContext context = createSessionContext();
168 ElementContext elementContext = new ElementContext(vspId, version.getId());
170 return zusammenAdaptor.listElementsByName(context, elementContext, null,
171 ElementType.OrchestrationTemplateCandidate.name()).stream()
172 .noneMatch(candidateSub -> ElementType.OrchestrationTemplateCandidateValidationData.name()
173 .equals(candidateSub.getInfo().getName()));
176 private boolean isEqual(OrchestrationTemplateEntity orchestrationTemplateEntity,
177 OrchestrationTemplateCandidateData orchestrationTemplateCandidateData) {
178 return orchestrationTemplateEntity.getFileName()
179 .equals(orchestrationTemplateCandidateData.getFileName()) &&
180 orchestrationTemplateEntity.getFileSuffix()
181 .equals(orchestrationTemplateCandidateData.getFileSuffix());
184 private boolean isProcessedEntityValid(OrchestrationTemplateEntity orchestrationTemplateEntity) {
185 return !orchestrationTemplateEntity.getValidationData().contains(ErrorLevel.ERROR.name());
188 private void populateCandidateValidationData(SessionContext context,
189 ElementContext elementContext,
190 Id candidateValidationElementId,
191 String validationData) {
192 ZusammenElement candidateValidationElement =
193 buildStructuralElement(ElementType.OrchestrationTemplateCandidateValidationData,
195 candidateValidationElement.setElementId(candidateValidationElementId);
196 candidateValidationElement.setData(new ByteArrayInputStream(validationData.getBytes()));
198 zusammenAdaptor.saveElement(context, elementContext, candidateValidationElement,
199 "Healed Orchestration Template Candidate Validation data");
202 private void populateOrchestrationTemplateStructure(InputStream processedFile,
203 Id structureElementId, VspDetails vspDetails,
204 SessionContext context,
205 ElementContext elementContext)
207 byte[] byteData = FileUtils.toByteArray(processedFile);
208 FileContentHandler contentMap =
209 CommonUtil.validateAndUploadFileContent(OnboardingTypesEnum.ZIP, byteData);
210 OrchestrationTemplateCandidateData orchestrationTemplateEntityData =
211 new CandidateEntityBuilder(candidateService)
212 .buildCandidateEntityFromZip(vspDetails, byteData, contentMap, null);
213 String fileDataStructure = orchestrationTemplateEntityData.getFilesDataStructure();
215 ZusammenElement orchestrationTemplateStructure =
216 buildStructuralElement(ElementType.OrchestrationTemplateStructure, Action.UPDATE);
217 orchestrationTemplateStructure.setElementId(structureElementId);
218 orchestrationTemplateStructure.setData(new ByteArrayInputStream(fileDataStructure.getBytes()));
220 zusammenAdaptor.saveElement(context, elementContext, orchestrationTemplateStructure,
221 "Healed Orchestration Template Structure");
224 private Element getOrchestrationTemplateElement(SessionContext context,
225 ElementContext elementContext) {
226 ElementInfo vspModelElement = zusammenAdaptor
227 .getElementInfoByName(context, elementContext, null, ElementType.VspModel.name())
228 .orElseThrow(() -> new CoreException(new ErrorCode.ErrorCodeBuilder()
229 .withMessage(MISSING_VSP_MODEL_ERROR).build()));
231 return getElement(context, elementContext, vspModelElement.getId(),
232 ElementType.OrchestrationTemplate, MISSING_ORCHESTRATION_TEMPLATE_ERROR);
235 private Element getOrchestrationTemplateValidationElement(
236 Collection<Element> orchestrationTemplateSubs) {
237 return orchestrationTemplateSubs.stream()
238 .filter(orchestrationTemplateSub -> ElementType.OrchestrationTemplateValidationData.name()
239 .equals(orchestrationTemplateSub.getInfo().getName()))
241 .orElseThrow(() -> new CoreException(new ErrorCode.ErrorCodeBuilder()
242 .withMessage(MISSING_ORCHESTRATION_TEMPLATE_VALIDATE_DATA_ERROR).build()));
246 private Element getCandidateContentElement(Collection<Element> candidateSubs) {
247 return candidateSubs.stream()
248 .filter(candidateSub -> ElementType.OrchestrationTemplateCandidateContent.name()
249 .equals(candidateSub.getInfo().getName()))
251 .orElseThrow(() -> new CoreException(new ErrorCode.ErrorCodeBuilder()
252 .withMessage(MISSING_ORCHESTRATION_TEMPLATE_CANDIDATE_CONTENT_ERROR).build()));
255 private Id createIfAbsentStructureElementId(Collection<Element> orchestrationTemplateSubs,
256 SessionContext context, ElementContext elementContext,
257 Element orchestrationTemplateElement) {
258 return orchestrationTemplateSubs.stream()
259 .filter(orchestrationTemplateSub -> ElementType.OrchestrationTemplateStructure.name()
260 .equals(orchestrationTemplateSub.getInfo().getName()))
261 .findFirst().map(Element::getElementId)
262 .orElse(addStructureSubElement(context, elementContext,
263 ElementType.OrchestrationTemplateStructure,
264 orchestrationTemplateElement.getElementId()));
267 private Id creatIfAbsentCandidateValidationElementId(Collection<Element> candidateSubs,
268 SessionContext context, ElementContext
269 elementContext, Element candidateElement) {
270 return candidateSubs.stream()
271 .filter(candidateSub -> ElementType.OrchestrationTemplateCandidateValidationData.name()
272 .equals(candidateSub.getInfo().getName()))
273 .findFirst().map(Element::getElementId)
274 .orElse(addStructureSubElement(context, elementContext,
275 ElementType.OrchestrationTemplateCandidateValidationData,
276 candidateElement.getElementId()));
279 private Element getElement(SessionContext context, ElementContext elementContext,
280 Id parentElementId, ElementType elementType, String errorMessage) {
281 return zusammenAdaptor
282 .getElementByName(context, elementContext, parentElementId, elementType.name())
283 .orElseThrow(() -> new CoreException(
284 new ErrorCode.ErrorCodeBuilder().withMessage(errorMessage).build()));
287 private OrchestrationTemplateEntity getOrchestrationTemplateEntity(
288 Element orchestrationTemplateElement, Element validationDataElement) {
289 OrchestrationTemplateEntity orchestrationTemplateEntity = new OrchestrationTemplateEntity();
291 if (isNotEmpty(orchestrationTemplateElement.getData())) {
292 orchestrationTemplateEntity.setContentData(
293 ByteBuffer.wrap(FileUtils.toByteArray(orchestrationTemplateElement.getData())));
295 orchestrationTemplateEntity.setFileSuffix(
296 validationDataElement.getInfo().getProperty(InfoPropertyName.FILE_SUFFIX.getVal()));
297 orchestrationTemplateEntity.setFileName(
298 validationDataElement.getInfo().getProperty(InfoPropertyName.FILE_NAME.getVal()));
299 if (isNotEmpty(validationDataElement.getData())) {
300 orchestrationTemplateEntity
301 .setValidationData(new String(FileUtils.toByteArray(validationDataElement.getData())));
303 return orchestrationTemplateEntity;
306 private OrchestrationTemplateCandidateData getCandidateData(Element candidateElement,
307 Element candidateContentElement) {
308 OrchestrationTemplateCandidateData candidateData = new OrchestrationTemplateCandidateData();
310 .setFilesDataStructure(new String(FileUtils.toByteArray(candidateElement.getData())));
312 .setContentData(ByteBuffer.wrap(FileUtils.toByteArray(candidateContentElement.getData())));
313 candidateData.setFileSuffix(
314 candidateContentElement.getInfo().getProperty(InfoPropertyName.FILE_SUFFIX.getVal()));
315 candidateData.setFileName(
316 candidateContentElement.getInfo().getProperty(InfoPropertyName.FILE_NAME.getVal()));
317 return candidateData;
320 private Id addStructureSubElement(SessionContext context, ElementContext elementContext,
321 ElementType elementType, Id parentElementId) {
322 ZusammenElement newElement = buildStructuralElement(elementType, Action.CREATE);
324 ZusammenElement parentElement = buildElement(parentElementId, Action.IGNORE);
325 parentElement.addSubElement(newElement);
327 return zusammenAdaptor.saveElement(context, elementContext, parentElement,
328 String.format("Add element %s under element id %s", elementType.name(), parentElementId))
329 .getSubElements().iterator().next().getElementId();
332 private void emptyStructureElementAndSub(SessionContext context, ElementContext elementContext,
333 Id elementId, ElementType elementType, Id subElementId,
334 ElementType subElementType) {
335 ZusammenElement subElement = buildStructuralElement(subElementType, Action.UPDATE);
336 subElement.setElementId(subElementId);
337 subElement.setData(new ByteArrayInputStream(EMPTY_DATA_BYTES));
339 ZusammenElement element = buildStructuralElement(elementType, Action.UPDATE);
340 element.setElementId(elementId);
341 element.setData(new ByteArrayInputStream(EMPTY_DATA_BYTES));
342 element.addSubElement(subElement);
344 zusammenAdaptor.saveElement(context, elementContext, element,
345 String.format("Empty element %s and its sub element %s", elementType.name(),
346 subElementType.name()));
349 public enum InfoPropertyName {
350 FILE_SUFFIX("fileSuffix"),
351 FILE_NAME("fileName");
355 InfoPropertyName(String val) {
359 private String getVal() {
364 private boolean isNotEmpty(InputStream elementData) {
365 byte[] byteElementData;
366 if (Objects.isNull(elementData)) {
370 byteElementData = IOUtils.toByteArray(elementData);
371 } catch (IOException e) {
374 return !ArrayUtils.isEmpty(byteElementData);