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.
18 package org.openecomp.sdcrests.vsp.rest.services;
20 import java.nio.ByteBuffer;
21 import java.nio.charset.StandardCharsets;
22 import java.security.KeyManagementException;
23 import java.security.NoSuchAlgorithmException;
24 import java.security.cert.X509Certificate;
25 import java.util.List;
26 import java.util.Objects;
27 import java.util.Optional;
28 import javax.inject.Named;
29 import javax.net.ssl.SSLContext;
30 import javax.net.ssl.TrustManager;
31 import javax.net.ssl.X509TrustManager;
32 import javax.ws.rs.client.Client;
33 import javax.ws.rs.client.ClientBuilder;
34 import javax.ws.rs.core.Response;
35 import org.onap.config.api.ConfigurationManager;
36 import org.openecomp.core.utilities.orchestration.OnboardingTypesEnum;
37 import org.openecomp.sdc.common.errors.CoreException;
38 import org.openecomp.sdc.common.errors.ErrorCode;
39 import org.openecomp.sdc.common.errors.ErrorCodeAndMessage;
40 import org.openecomp.sdc.common.errors.GeneralErrorBuilder;
41 import org.openecomp.sdc.logging.api.Logger;
42 import org.openecomp.sdc.logging.api.LoggerFactory;
43 import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManager;
44 import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManagerFactory;
45 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails;
46 import org.openecomp.sdc.vendorsoftwareproduct.types.OnboardPackageInfo;
47 import org.openecomp.sdc.vendorsoftwareproduct.types.UploadFileResponse;
48 import org.openecomp.sdc.versioning.VersioningManager;
49 import org.openecomp.sdc.versioning.VersioningManagerFactory;
50 import org.openecomp.sdc.versioning.dao.types.Version;
51 import org.openecomp.sdcrests.vendorsoftwareproducts.types.UploadFileResponseDto;
52 import org.openecomp.sdcrests.vsp.rest.VnfPackageRepository;
53 import org.openecomp.sdcrests.vsp.rest.mapping.MapUploadFileResponseToUploadFileResponseDto;
54 import org.springframework.context.annotation.Scope;
55 import org.springframework.stereotype.Service;
57 import static javax.ws.rs.core.HttpHeaders.CONTENT_DISPOSITION;
58 import static org.openecomp.core.utilities.file.FileUtils.getFileExtension;
59 import static org.openecomp.core.utilities.file.FileUtils.getNetworkPackageName;
62 * Enables integration API interface with VNF Repository (VNFSDK).
64 * <li>Get all the VNF Package Meta-data.</li>
65 * <li>Download a VNF Package.</li>
66 * <li>Import a VNF package to SDC catalog (Download & validate).</li>
69 * @version Amsterdam release (ONAP 1.0)
72 @Service("vnfPackageRepository")
73 @Scope(value = "prototype")
74 public class VnfPackageRepositoryImpl implements VnfPackageRepository {
76 private static final Logger LOGGER = LoggerFactory.getLogger(VnfPackageRepositoryImpl.class);
77 private static final Client CLIENT = ignoreSSLClient();
79 private static Client ignoreSSLClient() {
81 SSLContext sslcontext = SSLContext.getInstance("TLS");
82 sslcontext.init(null, new TrustManager[]{new X509TrustManager() {
83 public void checkClientTrusted(X509Certificate[] c, String s) {}
84 public void checkServerTrusted(X509Certificate[] c, String s) {}
85 public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
86 }}, new java.security.SecureRandom());
88 return ClientBuilder.newBuilder()
89 .sslContext(sslcontext)
90 .hostnameVerifier((a, b) -> true)
92 } catch (NoSuchAlgorithmException | KeyManagementException e) {
93 LOGGER.error("Failed to initialize SSL unsecure context", e);
95 return ClientBuilder.newClient();
97 private final Configuration config;
99 public VnfPackageRepositoryImpl(Configuration config) {
100 this.config = config;
103 public VnfPackageRepositoryImpl() {
104 this(new FileConfiguration());
108 public Response getVnfPackages(String vspId, String versionId, String user) {
109 LOGGER.debug("Get VNF Packages from Repository: {}", vspId);
110 final String getVnfPackageUri = config.getGetUri();
111 Response remoteResponse = CLIENT.target(getVnfPackageUri).request().get();
112 if (remoteResponse.getStatus() != Response.Status.OK.getStatusCode()) {
113 return handleUnexpectedStatus("querying VNF package metadata", getVnfPackageUri, remoteResponse);
115 LOGGER.debug("Response from VNF Repository: {}", remoteResponse);
116 return Response.ok(remoteResponse.readEntity(String.class)).build();
120 public Response importVnfPackage(String vspId, String versionId, String csarId, String user) {
121 LOGGER.debug("Import VNF Packages from Repository: {}", csarId);
122 final String downloadPackageUri = String.format(config.getDownloadUri(), csarId);
124 Response remoteResponse = CLIENT.target(downloadPackageUri).request().get();
125 if (remoteResponse.getStatus() != Response.Status.OK.getStatusCode()) {
126 return handleUnexpectedStatus("downloading VNF package", downloadPackageUri, remoteResponse);
129 LOGGER.debug("Response from VNF Repository for download package is success. URI={}", downloadPackageUri);
130 byte[] payload = remoteResponse.readEntity(String.class).getBytes(StandardCharsets.ISO_8859_1);
131 return uploadVnfPackage(vspId, versionId, csarId, payload);
134 private Response uploadVnfPackage(final String vspId, final String versionId,
135 final String csarId, final byte[] payload) {
137 final OrchestrationTemplateCandidateManager candidateManager =
138 OrchestrationTemplateCandidateManagerFactory.getInstance().createInterface();
139 final String filename = formatFilename(csarId);
140 final String fileExtension = getFileExtension(filename);
141 final OnboardPackageInfo onboardPackageInfo =
142 new OnboardPackageInfo(getNetworkPackageName(filename), fileExtension, ByteBuffer.wrap(payload),
143 OnboardingTypesEnum.getOnboardingTypesEnum(fileExtension));
144 final VspDetails vspDetails = new VspDetails(vspId, getVersion(vspId, versionId));
145 final UploadFileResponse response = candidateManager.upload(vspDetails, onboardPackageInfo);
146 final UploadFileResponseDto uploadFileResponse =
147 new MapUploadFileResponseToUploadFileResponseDto()
148 .applyMapping(response, UploadFileResponseDto.class);
150 return Response.ok(uploadFileResponse).build();
152 } catch (final Exception e) {
153 ErrorCode error = new GeneralErrorBuilder().build();
154 LOGGER.error("Exception while uploading package received from VNF Repository", new CoreException(error, e));
155 return generateInternalServerError(error);
160 public Response downloadVnfPackage(String vspId, String versionId, String csarId, String user) {
161 LOGGER.debug("Download VNF package from repository: csarId={}", csarId);
162 final String downloadPackageUri = String.format(config.getDownloadUri(), csarId);
164 Response remoteResponse = CLIENT.target(downloadPackageUri).request().get();
165 if (remoteResponse.getStatus() != Response.Status.OK.getStatusCode()) {
166 return handleUnexpectedStatus("downloading VNF package", downloadPackageUri, remoteResponse);
169 byte[] payload = remoteResponse.readEntity(String.class).getBytes(StandardCharsets.ISO_8859_1);
170 Response.ResponseBuilder response = Response.ok(payload);
171 response.header(CONTENT_DISPOSITION, "attachment; filename=" + formatFilename(csarId));
173 LOGGER.debug("Response from VNF Repository for download package is success. URI={}", downloadPackageUri);
174 return response.build();
177 private Version getVersion(String vspId, String versionId) {
178 VersioningManager versioningManager = VersioningManagerFactory.getInstance().createInterface();
179 return findVersion(versioningManager.list(vspId), versionId).orElse(new Version(versionId));
182 Optional<Version> findVersion(List<Version> versions, String requestedVersion) {
183 return versions.stream().filter(ver -> Objects.equals(ver.getId(), requestedVersion)).findAny();
186 private static Response handleUnexpectedStatus(String action, String uri, Response response) {
188 ErrorCode error = new GeneralErrorBuilder().build();
190 if (LOGGER.isErrorEnabled()) {
191 String body = response.hasEntity() ? response.readEntity(String.class) : "";
192 LOGGER.error("Unexpected response status while {}: URI={}, status={}, body={}", action, uri,
193 response.getStatus(), body, new CoreException(error));
196 return generateInternalServerError(error);
199 private static Response generateInternalServerError(ErrorCode error) {
200 ErrorCodeAndMessage payload = new ErrorCodeAndMessage(Response.Status.INTERNAL_SERVER_ERROR, error);
201 return Response.serverError().entity(payload).build();
204 private static String formatFilename(String csarId) {
205 return "temp_" + csarId + ".csar";
208 interface Configuration {
210 String getDownloadUri();
213 static class FileConfiguration implements Configuration {
216 public String getGetUri() {
217 return LazyFileConfiguration.INSTANCE.getGetUri();
221 public String getDownloadUri() {
222 return LazyFileConfiguration.INSTANCE.getDownloadUri();
225 private static class LazyFileConfiguration implements Configuration {
227 private static final String CONFIG_NAMESPACE = "vnfrepo";
229 private static final String DEFAULT_HOST = "localhost";
230 private static final String DEFAULT_PORT = "8702";
232 private static final String DEFAULT_URI_PREFIX = "/onapapi/vnfsdk-marketplace/v1/PackageResource/csars";
233 private static final String DEFAULT_LIST_URI = DEFAULT_URI_PREFIX + "/";
234 private static final String DEFAULT_DOWNLOAD_URI = DEFAULT_URI_PREFIX + "/%s/files";
236 private static final LazyFileConfiguration INSTANCE = new LazyFileConfiguration();
238 private final String getUri;
239 private final String downloadUri;
241 private LazyFileConfiguration() {
242 org.onap.config.api.Configuration config = ConfigurationManager.lookup();
243 String host = readConfig(config, "vnfRepoHost", DEFAULT_HOST);
244 String port = readConfig(config, "vnfRepoPort", DEFAULT_PORT);
245 String listPackagesUri = readConfig(config, "getVnfUri", DEFAULT_LIST_URI);
246 String downloadPackageUri = readConfig(config, "downloadVnfUri", DEFAULT_DOWNLOAD_URI);
247 this.getUri = formatUri(host, port, listPackagesUri);
248 this.downloadUri = formatUri(host, port, downloadPackageUri);
251 private String readConfig(org.onap.config.api.Configuration config, String key, String defaultValue) {
253 String value = config.getAsString(CONFIG_NAMESPACE, key);
254 return (value == null) ? defaultValue : value;
255 } catch (Exception e) {
256 LOGGER.error("Failed to read VNF repository configuration key '{}', default value '{}' will be used",
257 key, defaultValue, e);
262 private static String formatUri(String host, String port, String path) {
263 return "https://" + host + ":" + port + (path.startsWith("/") ? path : "/" + path);
266 public String getGetUri() {
270 public String getDownloadUri() {