2 * ============LICENSE_START=======================================================
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.onap.aai.modelloader.notification;
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;
49 * This class is responsible for downloading the artifacts from the ASDC.
51 * The downloads can be TOSCA_CSAR files or VNF_CATALOG files.
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.
56 * TOSCA_CSAR file artifacts will be converted into XML and returned as model artifacts.
59 public class ArtifactDownloadManager {
61 private static Logger logger = LoggerFactory.getInstance().getLogger(ArtifactDownloadManager.class);
63 private final IDistributionClient client;
64 private final NotificationPublisher notificationPublisher;
65 private final VnfCatalogExtractor vnfCatalogExtractor;
66 private final BabelArtifactService babelArtifactService;
68 public ArtifactDownloadManager(IDistributionClient client,
69 NotificationPublisher notificationPublisher, VnfCatalogExtractor vnfCatalogExtractor, BabelArtifactService babelArtifactService) {
71 this.notificationPublisher = notificationPublisher;
72 this.vnfCatalogExtractor = vnfCatalogExtractor;
73 this.babelArtifactService = babelArtifactService;
77 * This method downloads the artifacts from the ASDC.
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>
85 boolean downloadArtifacts(INotificationData data, List<IArtifactInfo> artifacts, List<Artifact> modelArtifacts,
86 List<Artifact> catalogArtifacts) {
87 boolean success = true;
89 for (IArtifactInfo artifact : artifacts) {
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());
96 } catch (Exception e) {
97 notificationPublisher.publishDeployFailure(client, data, artifact);
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));
116 IDistributionClientDownloadResult downloadResult = client.download(artifact);
118 logger.info(ModelLoaderMsgs.DOWNLOAD_COMPLETE, downloadResult.getDistributionActionResult().toString(),
119 downloadResult.getArtifactPayload() == null ? "null"
120 : Base64.getEncoder().encodeToString(downloadResult.getArtifactPayload()));
122 if (DistributionActionResultEnum.SUCCESS.equals(downloadResult.getDistributionActionResult())) {
123 logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Downloaded artifact: " + artifact.getArtifactName());
124 notificationPublisher.publishDownloadSuccess(client, data, artifact);
126 throw new DownloadFailureException(downloadResult.getDistributionMessageResult());
129 return downloadResult;
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);
141 logger.info(ModelLoaderMsgs.UNSUPPORTED_ARTIFACT_TYPE, artifactInfo.getArtifactName(),
142 artifactInfo.getArtifactType());
143 throw new InvalidArchiveException("Unsupported artifact type: " + artifactInfo.getArtifactType());
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);
157 // Get VNF Catalog artifacts directly from CSAR
158 List<Artifact> csarCatalogArtifacts = vnfCatalogExtractor.extract(payload, artifactInfo.getArtifactName());
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);
170 private void processModelQuerySpecArtifact(List<Artifact> modelArtifacts,
171 IDistributionClientDownloadResult downloadResult) throws BabelArtifactParsingException {
172 logger.debug(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Processing named query artifact.");
174 IModelParser parser = new NamedQueryArtifactParser();
176 List<Artifact> parsedArtifacts =
177 parser.parse(new String(downloadResult.getArtifactPayload()), downloadResult.getArtifactFilename());
179 if (parsedArtifactsExist(parsedArtifacts)) {
180 modelArtifacts.addAll(parsedArtifacts);
182 throw new BabelArtifactParsingException(
183 "Could not parse generated XML: " + new String(downloadResult.getArtifactPayload()));
187 private boolean parsedArtifactsExist(List<Artifact> parsedArtifacts) {
188 return parsedArtifacts != null && !parsedArtifacts.isEmpty();