Refactor babel-related code to not update parameter values
[aai/model-loader.git] / src / main / java / org / onap / aai / modelloader / notification / ArtifactDownloadManager.java
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
4  * ================================================================================
5  * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * Copyright © 2017-2018 European Software Marketing Ltd.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *       http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21 package org.onap.aai.modelloader.notification;
22
23 import java.time.ZonedDateTime;
24 import java.time.format.DateTimeFormatter;
25 import java.util.Base64;
26 import java.util.List;
27 import org.onap.aai.babel.service.data.BabelRequest;
28 import org.onap.aai.cl.api.Logger;
29 import org.onap.aai.cl.eelf.LoggerFactory;
30 import org.onap.aai.cl.mdc.MdcContext;
31 import org.onap.aai.cl.mdc.MdcOverride;
32 import org.onap.aai.modelloader.babel.BabelArtifactService;
33 import org.onap.aai.modelloader.entity.Artifact;
34 import org.onap.aai.modelloader.entity.model.BabelArtifactParsingException;
35 import org.onap.aai.modelloader.entity.model.IModelParser;
36 import org.onap.aai.modelloader.entity.model.NamedQueryArtifactParser;
37 import org.onap.aai.modelloader.extraction.InvalidArchiveException;
38 import org.onap.aai.modelloader.extraction.VnfCatalogExtractor;
39 import org.onap.aai.modelloader.service.ModelLoaderMsgs;
40 import org.onap.sdc.api.IDistributionClient;
41 import org.onap.sdc.api.notification.IArtifactInfo;
42 import org.onap.sdc.api.notification.INotificationData;
43 import org.onap.sdc.api.results.IDistributionClientDownloadResult;
44 import org.onap.sdc.utils.ArtifactTypeEnum;
45 import org.onap.sdc.utils.DistributionActionResultEnum;
46 import org.springframework.stereotype.Component;
47
48 /**
49  * This class is responsible for downloading the artifacts from the ASDC.
50  *
51  * The downloads can be TOSCA_CSAR files or VNF_CATALOG files.
52  *
53  * The status of the download is published. The status of the extraction of yml files from a TOSCA_CSAR file is also
54  * published as a deployment event.
55  *
56  * TOSCA_CSAR file artifacts will be converted into XML and returned as model artifacts.
57  */
58 @Component
59 public class ArtifactDownloadManager {
60
61     private static Logger logger = LoggerFactory.getInstance().getLogger(ArtifactDownloadManager.class);
62
63     private final IDistributionClient client;
64     private final NotificationPublisher notificationPublisher;
65     private final VnfCatalogExtractor vnfCatalogExtractor;
66     private final BabelArtifactService babelArtifactService;
67
68     public ArtifactDownloadManager(IDistributionClient client,
69             NotificationPublisher notificationPublisher, VnfCatalogExtractor vnfCatalogExtractor, BabelArtifactService babelArtifactService) {
70         this.client = client;
71         this.notificationPublisher = notificationPublisher;
72         this.vnfCatalogExtractor = vnfCatalogExtractor;
73         this.babelArtifactService = babelArtifactService;
74     }
75
76     /**
77      * This method downloads the artifacts from the ASDC.
78      *
79      * @param data data about the notification that is being processed
80      * @param artifacts the specific artifacts found in the data.
81      * @param modelArtifacts collection of artifacts for model query specs
82      * @param catalogArtifacts collection of artifacts that represent vnf catalog files
83      * @return boolean <code>true</code> if the download process was successful otherwise <code>false</code>
84      */
85     boolean downloadArtifacts(INotificationData data, List<IArtifactInfo> artifacts, List<Artifact> modelArtifacts,
86             List<Artifact> catalogArtifacts) {
87         boolean success = true;
88
89         for (IArtifactInfo artifact : artifacts) {
90             try {
91                 IDistributionClientDownloadResult downloadResult = downloadIndividualArtifacts(data, artifact);
92                 processDownloadedArtifacts(modelArtifacts, catalogArtifacts, artifact, downloadResult, data);
93             } catch (DownloadFailureException e) {
94                 notificationPublisher.publishDownloadFailure(client, data, artifact, e.getMessage());
95                 success = false;
96             } catch (Exception e) {
97                 notificationPublisher.publishDeployFailure(client, data, artifact);
98                 success = false;
99             }
100
101             if (!success) {
102                 break;
103             }
104         }
105
106         return success;
107     }
108
109     private IDistributionClientDownloadResult downloadIndividualArtifacts(INotificationData data,
110             IArtifactInfo artifact) throws DownloadFailureException {
111         // Grab the current time so we can measure the download time for the metrics log
112         DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
113         MdcOverride override = new MdcOverride();
114         override.addAttribute(MdcContext.MDC_START_TIME, ZonedDateTime.now().format(formatter));
115
116         IDistributionClientDownloadResult downloadResult = client.download(artifact);
117
118         logger.info(ModelLoaderMsgs.DOWNLOAD_COMPLETE, downloadResult.getDistributionActionResult().toString(),
119                 downloadResult.getArtifactPayload() == null ? "null"
120                         : Base64.getEncoder().encodeToString(downloadResult.getArtifactPayload()));
121
122         if (DistributionActionResultEnum.SUCCESS.equals(downloadResult.getDistributionActionResult())) {
123             logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Downloaded artifact: " + artifact.getArtifactName());
124             notificationPublisher.publishDownloadSuccess(client, data, artifact);
125         } else {
126             throw new DownloadFailureException(downloadResult.getDistributionMessageResult());
127         }
128
129         return downloadResult;
130     }
131
132     private void processDownloadedArtifacts(List<Artifact> modelArtifacts, List<Artifact> catalogArtifacts,
133             IArtifactInfo artifactInfo, IDistributionClientDownloadResult downloadResult, INotificationData data)
134             throws ProcessToscaArtifactsException, InvalidArchiveException, BabelArtifactParsingException {
135         if ("TOSCA_CSAR".equalsIgnoreCase(artifactInfo.getArtifactType())) {
136             processToscaArtifacts(modelArtifacts, catalogArtifacts, downloadResult.getArtifactPayload(), artifactInfo,
137                     data.getDistributionID(), data.getServiceVersion());
138         } else if (ArtifactTypeEnum.MODEL_QUERY_SPEC.toString().equalsIgnoreCase(artifactInfo.getArtifactType())) {
139             processModelQuerySpecArtifact(modelArtifacts, downloadResult);
140         } else {
141             logger.info(ModelLoaderMsgs.UNSUPPORTED_ARTIFACT_TYPE, artifactInfo.getArtifactName(),
142                     artifactInfo.getArtifactType());
143             throw new InvalidArchiveException("Unsupported artifact type: " + artifactInfo.getArtifactType());
144         }
145     }
146
147     public void processToscaArtifacts(List<Artifact> modelArtifacts, List<Artifact> catalogArtifacts, byte[] payload,
148             IArtifactInfo artifactInfo, String distributionId, String serviceVersion)
149             throws ProcessToscaArtifactsException, InvalidArchiveException {
150         // Get translated artifacts from Babel Service
151         BabelRequest babelRequest = new BabelRequest();
152         babelRequest.setArtifactName(artifactInfo.getArtifactName());
153         babelRequest.setCsar(Base64.getEncoder().encodeToString(payload));
154         babelRequest.setArtifactVersion(serviceVersion);
155         babelArtifactService.invokeBabelService(modelArtifacts, catalogArtifacts, babelRequest, distributionId);
156
157         // Get VNF Catalog artifacts directly from CSAR
158         List<Artifact> csarCatalogArtifacts = vnfCatalogExtractor.extract(payload, artifactInfo.getArtifactName());
159
160         // Throw an error if VNF Catalog data is present in the Babel payload and directly in the CSAR
161         if (!catalogArtifacts.isEmpty() && !csarCatalogArtifacts.isEmpty()) {
162             logger.error(ModelLoaderMsgs.DUPLICATE_VNFC_DATA_ERROR, artifactInfo.getArtifactName());
163             throw new InvalidArchiveException("CSAR: " + artifactInfo.getArtifactName()
164                     + " contains VNF Catalog data in the format of both TOSCA and XML files. Only one format can be used for each CSAR file.");
165         } else if (!csarCatalogArtifacts.isEmpty()) {
166             catalogArtifacts.addAll(csarCatalogArtifacts);
167         }
168     }
169
170     private void processModelQuerySpecArtifact(List<Artifact> modelArtifacts,
171             IDistributionClientDownloadResult downloadResult) throws BabelArtifactParsingException {
172         logger.debug(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Processing named query artifact.");
173
174         IModelParser parser = new NamedQueryArtifactParser();
175
176         List<Artifact> parsedArtifacts =
177                 parser.parse(new String(downloadResult.getArtifactPayload()), downloadResult.getArtifactFilename());
178
179         if (parsedArtifactsExist(parsedArtifacts)) {
180             modelArtifacts.addAll(parsedArtifacts);
181         } else {
182             throw new BabelArtifactParsingException(
183                     "Could not parse generated XML: " + new String(downloadResult.getArtifactPayload()));
184         }
185     }
186
187     private boolean parsedArtifactsExist(List<Artifact> parsedArtifacts) {
188         return parsedArtifacts != null && !parsedArtifacts.isEmpty();
189     }
190 }