2 * Copyright 2017 Huawei Technologies Co., Ltd.
3 * Modifications Copyright 2018 European Support Limited
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 package org.openecomp.sdcrests.vsp.rest.services;
19 import org.onap.config.api.ConfigurationManager;
20 import org.onap.config.api.JettySSLUtils;
21 import org.openecomp.core.utilities.orchestration.OnboardingTypesEnum;
22 import org.openecomp.sdc.common.errors.CoreException;
23 import org.openecomp.sdc.common.errors.ErrorCode;
24 import org.openecomp.sdc.common.errors.ErrorCodeAndMessage;
25 import org.openecomp.sdc.common.errors.GeneralErrorBuilder;
26 import org.openecomp.sdc.logging.api.Logger;
27 import org.openecomp.sdc.logging.api.LoggerFactory;
28 import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManager;
29 import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManagerFactory;
30 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails;
31 import org.openecomp.sdc.vendorsoftwareproduct.types.OnboardPackageInfo;
32 import org.openecomp.sdc.vendorsoftwareproduct.types.UploadFileResponse;
33 import org.openecomp.sdc.versioning.VersioningManager;
34 import org.openecomp.sdc.versioning.VersioningManagerFactory;
35 import org.openecomp.sdc.versioning.dao.types.Version;
36 import org.openecomp.sdcrests.vendorsoftwareproducts.types.UploadFileResponseDto;
37 import org.openecomp.sdcrests.vsp.rest.VnfPackageRepository;
38 import org.openecomp.sdcrests.vsp.rest.mapping.MapUploadFileResponseToUploadFileResponseDto;
39 import org.springframework.context.annotation.Scope;
40 import org.springframework.stereotype.Service;
42 import javax.inject.Named;
43 import javax.ws.rs.client.Client;
44 import javax.ws.rs.client.ClientBuilder;
45 import javax.ws.rs.core.Response;
46 import java.nio.ByteBuffer;
47 import java.nio.charset.StandardCharsets;
48 import java.util.List;
49 import java.util.Objects;
50 import java.util.Optional;
52 import static javax.ws.rs.core.HttpHeaders.CONTENT_DISPOSITION;
53 import static org.openecomp.core.utilities.file.FileUtils.getFileExtension;
54 import static org.openecomp.core.utilities.file.FileUtils.getNetworkPackageName;
57 * Enables integration API interface with VNF Repository (VNFSDK).
59 * <li>Get all the VNF Package Meta-data.</li>
60 * <li>Download a VNF Package.</li>
61 * <li>Import a VNF package to SDC catalog (Download & validate).</li>
64 * @version Amsterdam release (ONAP 1.0)
67 @Service("vnfPackageRepository")
68 @Scope(value = "prototype")
69 public class VnfPackageRepositoryImpl implements VnfPackageRepository {
71 private static final Logger LOGGER = LoggerFactory.getLogger(VnfPackageRepositoryImpl.class);
72 private static final Client CLIENT = trustSSLClient();
74 private static Client trustSSLClient() {
76 return ClientBuilder.newBuilder()
77 .sslContext(JettySSLUtils.getSslContext())
78 .hostnameVerifier((requestedHost, remoteServerSession) -> requestedHost.equalsIgnoreCase(remoteServerSession.getPeerHost())).build();
79 } catch (final Exception e) {
80 LOGGER.error("Failed to initialize SSL context", e);
82 return ClientBuilder.newClient();
85 private final Configuration config;
87 public VnfPackageRepositoryImpl(Configuration config) {
91 public VnfPackageRepositoryImpl() {
92 this(new FileConfiguration());
96 public Response getVnfPackages(String vspId, String versionId, String user) {
97 LOGGER.debug("Get VNF Packages from Repository: {}", vspId);
98 final String getVnfPackageUri = config.getGetUri();
99 Response remoteResponse = CLIENT.target(getVnfPackageUri).request().get();
100 if (remoteResponse.getStatus() != Response.Status.OK.getStatusCode()) {
101 return handleUnexpectedStatus("querying VNF package metadata", getVnfPackageUri, remoteResponse);
103 LOGGER.debug("Response from VNF Repository: {}", remoteResponse);
104 return Response.ok(remoteResponse.readEntity(String.class)).build();
108 public Response importVnfPackage(String vspId, String versionId, String csarId, String user) {
109 LOGGER.debug("Import VNF Packages from Repository: {}", csarId);
110 final String downloadPackageUri = String.format(config.getDownloadUri(), csarId);
111 Response remoteResponse = CLIENT.target(downloadPackageUri).request().get();
112 if (remoteResponse.getStatus() != Response.Status.OK.getStatusCode()) {
113 return handleUnexpectedStatus("downloading VNF package", downloadPackageUri, remoteResponse);
115 LOGGER.debug("Response from VNF Repository for download package is success. URI={}", downloadPackageUri);
116 byte[] payload = remoteResponse.readEntity(String.class).getBytes(StandardCharsets.ISO_8859_1);
117 return uploadVnfPackage(vspId, versionId, csarId, payload);
120 private Response uploadVnfPackage(final String vspId, final String versionId, final String csarId, final byte[] payload) {
122 final OrchestrationTemplateCandidateManager candidateManager = OrchestrationTemplateCandidateManagerFactory.getInstance()
124 final String filename = formatFilename(csarId);
125 final String fileExtension = getFileExtension(filename);
126 final OnboardPackageInfo onboardPackageInfo = new OnboardPackageInfo(getNetworkPackageName(filename), fileExtension,
127 ByteBuffer.wrap(payload), OnboardingTypesEnum.getOnboardingTypesEnum(fileExtension));
128 final VspDetails vspDetails = new VspDetails(vspId, getVersion(vspId, versionId));
129 final UploadFileResponse response = candidateManager.upload(vspDetails, onboardPackageInfo);
130 final UploadFileResponseDto uploadFileResponse = new MapUploadFileResponseToUploadFileResponseDto()
131 .applyMapping(response, UploadFileResponseDto.class);
132 return Response.ok(uploadFileResponse).build();
133 } catch (final Exception e) {
134 ErrorCode error = new GeneralErrorBuilder().build();
135 LOGGER.error("Exception while uploading package received from VNF Repository", new CoreException(error, e));
136 return generateInternalServerError(error);
141 public Response downloadVnfPackage(String vspId, String versionId, String csarId, String user) {
142 LOGGER.debug("Download VNF package from repository: csarId={}", csarId);
143 final String downloadPackageUri = String.format(config.getDownloadUri(), csarId);
144 Response remoteResponse = CLIENT.target(downloadPackageUri).request().get();
145 if (remoteResponse.getStatus() != Response.Status.OK.getStatusCode()) {
146 return handleUnexpectedStatus("downloading VNF package", downloadPackageUri, remoteResponse);
148 byte[] payload = remoteResponse.readEntity(String.class).getBytes(StandardCharsets.ISO_8859_1);
149 Response.ResponseBuilder response = Response.ok(payload);
150 response.header(CONTENT_DISPOSITION, "attachment; filename=" + formatFilename(csarId));
151 LOGGER.debug("Response from VNF Repository for download package is success. URI={}", downloadPackageUri);
152 return response.build();
155 private Version getVersion(String vspId, String versionId) {
156 VersioningManager versioningManager = VersioningManagerFactory.getInstance().createInterface();
157 return findVersion(versioningManager.list(vspId), versionId).orElse(new Version(versionId));
160 Optional<Version> findVersion(List<Version> versions, String requestedVersion) {
161 return versions.stream().filter(ver -> Objects.equals(ver.getId(), requestedVersion)).findAny();
164 private static Response handleUnexpectedStatus(String action, String uri, Response response) {
165 ErrorCode error = new GeneralErrorBuilder().build();
166 if (LOGGER.isErrorEnabled()) {
167 String body = response.hasEntity() ? response.readEntity(String.class) : "";
168 LOGGER.error("Unexpected response status while {}: URI={}, status={}, body={}", action, uri, response.getStatus(), body,
169 new CoreException(error));
171 return generateInternalServerError(error);
174 private static Response generateInternalServerError(ErrorCode error) {
175 ErrorCodeAndMessage payload = new ErrorCodeAndMessage(Response.Status.INTERNAL_SERVER_ERROR, error);
176 return Response.serverError().entity(payload).build();
179 private static String formatFilename(String csarId) {
180 return "temp_" + csarId + ".csar";
183 interface Configuration {
187 String getDownloadUri();
190 static class FileConfiguration implements Configuration {
193 public String getGetUri() {
194 return LazyFileConfiguration.INSTANCE.getGetUri();
198 public String getDownloadUri() {
199 return LazyFileConfiguration.INSTANCE.getDownloadUri();
202 private static class LazyFileConfiguration implements Configuration {
204 private static final String CONFIG_NAMESPACE = "vnfrepo";
205 private static final String DEFAULT_HOST = "localhost";
206 private static final String DEFAULT_PORT = "8702";
207 private static final String DEFAULT_URI_PREFIX = "/onapapi/vnfsdk-marketplace/v1/PackageResource/csars";
208 private static final String DEFAULT_LIST_URI = DEFAULT_URI_PREFIX + "/";
209 private static final String DEFAULT_DOWNLOAD_URI = DEFAULT_URI_PREFIX + "/%s/files";
210 private static final LazyFileConfiguration INSTANCE = new LazyFileConfiguration();
211 private final String getUri;
212 private final String downloadUri;
214 private LazyFileConfiguration() {
215 org.onap.config.api.Configuration config = ConfigurationManager.lookup();
216 String host = readConfig(config, "vnfRepoHost", DEFAULT_HOST);
217 String port = readConfig(config, "vnfRepoPort", DEFAULT_PORT);
218 String listPackagesUri = readConfig(config, "getVnfUri", DEFAULT_LIST_URI);
219 String downloadPackageUri = readConfig(config, "downloadVnfUri", DEFAULT_DOWNLOAD_URI);
220 this.getUri = formatUri(host, port, listPackagesUri);
221 this.downloadUri = formatUri(host, port, downloadPackageUri);
224 private String readConfig(org.onap.config.api.Configuration config, String key, String defaultValue) {
226 String value = config.getAsString(CONFIG_NAMESPACE, key);
227 return (value == null) ? defaultValue : value;
228 } catch (Exception e) {
229 LOGGER.error("Failed to read VNF repository configuration key '{}', default value '{}' will be used", key, defaultValue, e);
234 private static String formatUri(String host, String port, String path) {
235 return "https://" + host + ":" + port + (path.startsWith("/") ? path : "/" + path);
238 public String getGetUri() {
242 public String getDownloadUri() {