2 * Copyright 2017 Huawei Technologies Co., Ltd.
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.onap.vnfsdk.marketplace.wrapper;
19 import java.io.BufferedInputStream;
21 import java.io.FileInputStream;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.List;
27 import java.util.concurrent.Callable;
28 import java.util.concurrent.ExecutorService;
29 import java.util.concurrent.Executors;
31 import javax.ws.rs.core.HttpHeaders;
32 import javax.ws.rs.core.MediaType;
33 import javax.ws.rs.core.Response;
34 import javax.ws.rs.core.Response.Status;
36 import org.apache.commons.io.IOUtils;
37 import org.apache.commons.lang3.StringUtils;
38 import org.eclipse.jetty.http.HttpStatus;
39 import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
40 import org.onap.vnfsdk.marketplace.common.CommonConstant;
41 import org.onap.vnfsdk.marketplace.common.CommonErrorResponse;
42 import org.onap.vnfsdk.marketplace.common.FileUtil;
43 import org.onap.vnfsdk.marketplace.common.RestUtil;
44 import org.onap.vnfsdk.marketplace.common.ToolUtil;
45 import org.onap.vnfsdk.marketplace.db.entity.PackageData;
46 import org.onap.vnfsdk.marketplace.db.exception.ErrorCodeException;
47 import org.onap.vnfsdk.marketplace.db.exception.MarketplaceResourceException;
48 import org.onap.vnfsdk.marketplace.db.resource.PackageManager;
49 import org.onap.vnfsdk.marketplace.db.util.MarketplaceDbUtil;
50 import org.onap.vnfsdk.marketplace.entity.request.PackageBasicInfo;
51 import org.onap.vnfsdk.marketplace.entity.response.PackageMeta;
52 import org.onap.vnfsdk.marketplace.entity.response.UploadPackageResponse;
53 import org.onap.vnfsdk.marketplace.filemanage.FileManagerFactory;
54 import org.onap.vnfsdk.marketplace.onboarding.entity.OnBoardingOperResult;
55 import org.onap.vnfsdk.marketplace.onboarding.entity.OnBoardingResult;
56 import org.onap.vnfsdk.marketplace.onboarding.entity.OnBoardingSteps;
57 import org.onap.vnfsdk.marketplace.onboarding.entity.OnBoradingRequest;
58 import org.onap.vnfsdk.marketplace.onboarding.hooks.functiontest.FunctionTestExceutor;
59 import org.onap.vnfsdk.marketplace.onboarding.hooks.functiontest.FunctionTestHook;
60 import org.onap.vnfsdk.marketplace.onboarding.hooks.validatelifecycle.ValidateLifecycleTestResponse;
61 import org.onap.vnfsdk.marketplace.onboarding.onboardmanager.OnBoardingHandler;
62 import org.open.infc.grpc.Result;
63 import org.open.infc.grpc.client.OpenRemoteCli;
64 import org.slf4j.Logger;
65 import org.slf4j.LoggerFactory;
67 public class PackageWrapper {
69 private static PackageWrapper packageWrapper;
71 private static final Logger LOG = LoggerFactory.getLogger(PackageWrapper.class);
73 private static final boolean disableValidation = true;
76 * get PackageWrapper instance.
78 * @return package wrapper instance
80 public static PackageWrapper getInstance() {
81 if(packageWrapper == null) {
82 packageWrapper = new PackageWrapper();
84 return packageWrapper;
87 public Response updateValidateStatus(InputStream inputStream) throws IOException {
88 String reqParam = IOUtils.toString(inputStream);
89 LOG.info("updateValidateStatus request param:" + reqParam);
90 if(StringUtils.isBlank(reqParam)) {
91 LOG.error("The updateValidateStatus request params can't be null");
92 return Response.status(Status.EXPECTATION_FAILED).build();
95 ValidateLifecycleTestResponse lyfValidateResp = null; // TBD - Use Gson - jackson has
97 // JsonUtil.fromJson(reqParam, ValidateLifecycleTestResponse.class);
98 if(!checkOperationSucess(lyfValidateResp)) {
99 return Response.status(Status.EXPECTATION_FAILED).build();
102 String funcTestResponse = FunctionTestExceutor.executeFunctionTest(reqParam);
103 if(null == funcTestResponse) {
104 return Response.status(Status.EXPECTATION_FAILED).build();
107 if(!funcTestResponse.contains(CommonConstant.SUCCESS_STR)) {
108 return Response.status(Status.EXPECTATION_FAILED).build();
111 return Response.ok().build();
114 private boolean checkOperationSucess(ValidateLifecycleTestResponse lyfValidateResp) {
115 boolean bOperStatus = false;
116 if(null == lyfValidateResp) {
117 LOG.error("ValidateLifecycleTestResponse is NUll !!!");
120 if(lyfValidateResp.getLifecycle_status().equalsIgnoreCase(CommonConstant.SUCCESS_STR)
121 && lyfValidateResp.getValidate_status().equalsIgnoreCase(CommonConstant.SUCCESS_STR)) {
122 LOG.error("Lifecycle/Validation Response failed :" + lyfValidateResp.getLifecycle_status() + File.separator
123 + lyfValidateResp.getValidate_status());
130 * query package list by condition.
132 * @param name package name
133 * @param provider package provider
134 * @param version package version
135 * @param deletionPending package deletionPending
136 * @param type package type
139 public Response queryPackageListByCond(String name, String provider, String version, String deletionPending,
141 List<PackageData> dbresult = new ArrayList<>();
142 List<PackageMeta> result = new ArrayList<>();
143 LOG.info("query package info.name:" + name + " provider:" + provider + " version" + version + " deletionPending"
144 + deletionPending + " type:" + type);
146 dbresult = PackageManager.getInstance().queryPackage(name, provider, version, deletionPending, type);
147 result = PackageWrapperUtil.packageDataList2PackageMetaList(dbresult);
148 return Response.ok(ToolUtil.objectToString(result)).build();
149 } catch(MarketplaceResourceException e1) {
150 LOG.error("query package by csarId from db error ! ", e1);
151 return RestUtil.getRestException(e1.getMessage());
156 * query package by id.
158 * @param csarId package id
161 public Response queryPackageById(String csarId) {
162 PackageData dbResult = PackageWrapperUtil.getPackageInfoById(csarId);
163 PackageMeta result = PackageWrapperUtil.packageData2PackageMeta(dbResult);
164 return Response.ok(ToolUtil.objectToString(result)).build();
170 * @param uploadedInputStream inputStream
171 * @param fileDetail package detail
172 * @param head http header
174 * @throws Exception e
176 public Response uploadPackage(InputStream uploadedInputStream, FormDataContentDisposition fileDetail,
177 String details, HttpHeaders head) {
178 LOG.info("Upload/Reupload request Received !!!!");
180 String packageId = MarketplaceDbUtil.generateId();
181 return handlePackageUpload(packageId, uploadedInputStream, fileDetail, details, head);
182 } catch(IOException e) {
183 LOG.error("can't get package id", e);
185 return Response.status(Status.INTERNAL_SERVER_ERROR).build();
188 private UploadPackageResponse manageUpload(String packageId, String fileName, String fileLocation, String details,
189 String contentRange) throws IOException, ErrorCodeException {
190 String localDirName = ToolUtil.getTempDir(CommonConstant.CATALOG_CSAR_DIR_NAME, fileName);
191 PackageBasicInfo basicInfo = PackageWrapperUtil.getPacageBasicInfo(fileLocation);
192 UploadPackageResponse result = new UploadPackageResponse();
193 Boolean isEnd = PackageWrapperUtil.isUploadEnd(contentRange);
195 PackageMeta packageMeta =
196 PackageWrapperUtil.getPackageMeta(packageId, fileName, fileLocation, basicInfo, details);
198 String path = basicInfo.getType().toString() + File.separator + basicInfo.getProvider() + File.separator
199 + packageMeta.getCsarId() + File.separator + fileName.replace(".csar", "") + File.separator
200 + basicInfo.getVersion();
202 String dowloadUri = File.separator + path + File.separator;
203 packageMeta.setDownloadUri(dowloadUri);
205 LOG.info("dest path is : " + path);
206 LOG.info("packageMeta = " + ToolUtil.objectToString(packageMeta));
208 PackageData packageData = PackageWrapperUtil.getPackageData(packageMeta);
210 List<PackageData> lstPkgData =
211 PackageManager.getInstance().queryPackage(packageMeta.getName(), "", "", "", "");
212 if(!lstPkgData.isEmpty()) {
213 LOG.error("Package name is not unique");
214 throw new ErrorCodeException(HttpStatus.INTERNAL_SERVER_ERROR_500, "Package name already exists");
217 String destPath = File.separator + path + File.separator + File.separator;
218 boolean uploadResult = FileManagerFactory.createFileManager().upload(localDirName, destPath);
220 OnBoradingRequest oOnboradingRequest = new OnBoradingRequest();
221 oOnboradingRequest.setCsarId(packageId);
222 oOnboradingRequest.setPackageName(fileName);
223 oOnboradingRequest.setPackagePath(localDirName);
225 packageData.setCsarId(packageId);
226 packageData.setDownloadCount(-1);
227 PackageData packateDbData = PackageManager.getInstance().addPackage(packageData);
229 LOG.info("Store package data to database succed ! packateDbData = "
230 + ToolUtil.objectToString(packateDbData));
231 LOG.info("upload package file end, fileName:" + fileName);
233 result.setCsarId(packateDbData.getCsarId());
235 addOnBoardingRequest(oOnboradingRequest);
237 LOG.info("OnboradingRequest Data : " + ToolUtil.objectToString(oOnboradingRequest));
239 } catch(NullPointerException e) {
240 LOG.error("Package basicInfo is incorrect ! basicIonfo = " + ToolUtil.objectToString(basicInfo), e);
248 * Interface for Uploading package
251 * @param uploadedInputStream
256 * @throws IOException
257 * @throws MarketplaceResourceException
259 private Response handlePackageUpload(String packageId, InputStream uploadedInputStream,
260 FormDataContentDisposition fileDetail, String details, HttpHeaders head) throws IOException {
261 boolean bResult = handleDataValidate(packageId, uploadedInputStream, fileDetail);
263 LOG.error("Validation of Input received for Package Upload failed !!!");
264 return Response.status(Status.EXPECTATION_FAILED)
265 .entity(new CommonErrorResponse("Input package is empty or exception happened during validation"))
269 String fileName = "temp_" + packageId + ".csar";
270 if(null != fileDetail) {
271 LOG.info("the fileDetail = " + ToolUtil.objectToString(fileDetail));
273 fileName = ToolUtil.processFileName(fileDetail.getFileName());
276 String localDirName = ToolUtil.getTempDir(CommonConstant.CATALOG_CSAR_DIR_NAME, fileName);
278 String contentRange = null;
280 contentRange = head.getHeaderString(CommonConstant.HTTP_HEADER_CONTENT_RANGE);
282 LOG.info("store package chunk file, fileName:" + fileName + ",contentRange:" + contentRange);
283 if(ToolUtil.isEmptyString(contentRange)) {
284 int fileSize = uploadedInputStream.available();
285 contentRange = "0-" + fileSize + "/" + fileSize;
288 String fileLocation = ToolUtil.storeChunkFileInLocal(localDirName, fileName, uploadedInputStream);
289 LOG.info("the fileLocation when upload package is :" + fileLocation);
291 uploadedInputStream.close();
293 if (!disableValidation) {
295 Result result = OpenRemoteCli.run("localhost", 50051, null, Arrays.asList(new String[] { "--product", "onap-vtp", "csar-validate", "--csar", fileLocation, "--format", "json" }));
296 LOG.info("CSAR validation is successful" + result.getOutput());
298 int exitCode = result.getExitCode();
299 String output = result.getOutput();
301 if((exitCode != 0) || !output.contains("\"error\":\"SUCCESS\"")) {
302 LOG.error("Could not validate failed");
303 return Response.status(Status.EXPECTATION_FAILED).entity(new CommonErrorResponse(output))
306 } catch (Exception e) {
307 LOG.error("CSAR validation panicked", e);
308 return Response.serverError().entity(
309 new CommonErrorResponse("Exception occurred while validating csar package:" + e.getMessage()))
314 UploadPackageResponse result = null;
316 result = manageUpload(packageId, fileName, fileLocation, details, contentRange);
317 } catch(ErrorCodeException e) {
318 return Response.status(Status.EXPECTATION_FAILED)
319 .entity(new CommonErrorResponse("Package Name already exists")).build();
322 return Response.ok(ToolUtil.objectToString(result), MediaType.APPLICATION_JSON).build();
324 return Response.serverError().build();
329 * Execute OnBarding request
331 * @param oOnboradingRequest
333 private void addOnBoardingRequest(final OnBoradingRequest oOnboradingRequest) {
334 ExecutorService es = Executors.newFixedThreadPool(CommonConstant.ONBOARDING_THREAD_COUNT);
335 Callable<Integer> callableInteger = () -> {
336 new OnBoardingHandler().handleOnBoardingReq(oOnboradingRequest);
337 return CommonConstant.SUCESS;
339 es.submit(callableInteger);
343 * delete package by package id.
345 * @param csarId package id
348 public Response delPackage(String csarId) {
349 LOG.info("delete package info.csarId:" + csarId);
350 if(ToolUtil.isEmptyString(csarId)) {
351 LOG.error("delete package fail, csarid is null");
352 return Response.serverError().build();
354 deletePackageDataById(csarId);
355 return Response.ok().build();
359 * Delete Package by CSAR ID
363 private void deletePackageDataById(String csarId) {
364 String packagePath = PackageWrapperUtil.getPackagePath(csarId);
365 if(packagePath == null) {
366 LOG.error("package path is null! ");
370 FileManagerFactory.createFileManager().delete(packagePath);
371 // Delete Results Data
372 FileManagerFactory.createFileManager().delete(File.separator + csarId);
374 // delete package data from database
376 PackageManager.getInstance().deletePackage(csarId);
377 } catch(MarketplaceResourceException e1) {
378 LOG.error("delete package by csarId from db error ! " + e1.getMessage(), e1);
383 * download package by package id.
385 * @param csarId package id
388 public Response downloadCsarPackagesById(String csarId) {
389 PackageData packageData = PackageWrapperUtil.getPackageInfoById(csarId);
391 String packageName = packageData.getName();
392 String path = org.onap.vnfsdk.marketplace.filemanage.http.ToolUtil.getHttpServerAbsolutePath()
393 + File.separatorChar + packageData.getType() + File.separatorChar + packageData.getProvider()
394 + File.separatorChar + packageData.getCsarId() + File.separator + packageName + File.separatorChar
395 + packageData.getVersion() + File.separator + packageName + ".csar";
397 LOG.info("downloadCsarPackagesById path is : " + path);
399 File csarFile = new File(path);
400 if(!csarFile.exists()) {
401 return Response.status(Status.INTERNAL_SERVER_ERROR).build();
404 LOG.info("downloadCsarPackagesById ABS path is : " + csarFile.getAbsolutePath());
407 InputStream fis = new BufferedInputStream(new FileInputStream(csarFile.getAbsolutePath()));
408 return Response.ok(fis).header("Content-Disposition", "attachment; filename=\"" + csarFile.getName() + "\"")
410 } catch(Exception e1) {
411 LOG.error("download vnf package fail.", e1);
412 return RestUtil.getRestException(e1.getMessage());
417 * get package file uri.
419 * @param csarId package id
420 * @param relativePath file relative path
423 public Response getCsarFileUri(String csarId) {
424 return downloadCsarPackagesById(csarId);
428 * Interface to Update Download count for CSAR ID
433 public Response updateDwonloadCount(String csarId) {
434 return handleDownladCountUpdate(csarId) ? Response.ok().build()
435 : Response.status(Status.EXPECTATION_FAILED).build();
439 * Handle downlowa count update
444 private boolean handleDownladCountUpdate(String csarId) {
445 boolean bupdateSucess = false;
447 PackageManager.getInstance().updateDownloadCount(csarId);
448 bupdateSucess = true;
449 } catch(Exception exp) {
450 LOG.error("Updating Donwload count failed for Package with ID !!! : " + exp.getMessage(), exp);
452 return bupdateSucess;
456 * Interface to Re upload Package
459 * @param uploadedInputStream
466 public Response reUploadPackage(String csarId, InputStream uploadedInputStream,
467 FormDataContentDisposition fileDetail, String details, HttpHeaders head)
468 throws MarketplaceResourceException {
469 LOG.info("Reupload request Received !!!!");
471 // STEP 1: Validate Input Data
472 // ----------------------------
473 boolean bResult = handleDataValidate(csarId, uploadedInputStream, fileDetail);
475 LOG.error("Validation of Input received for Package Upload failed during Reload!!!");
476 return Response.status(Status.EXPECTATION_FAILED).build();
480 // STEP 2: Delete All Package Data based on package id
481 // ----------------------------------------------------
482 deletePackageDataById(csarId);
484 // STEP 3: upload package with same package id
485 // -------------------------------------------
486 return handlePackageUpload(csarId, uploadedInputStream, fileDetail, details, head);
487 } catch(IOException e) {
488 LOG.error("delete package failed", e);
490 return Response.status(Status.INTERNAL_SERVER_ERROR).build();
494 * Interface to get OnBoarding Result by Operation Type
501 public Response getOnBoardingResult(String csarId, String operTypeId, String operId) {
502 LOG.info("getOnBoardingResult request : csarId:" + csarId + " operTypeId:" + operTypeId + " operId:" + operId);
504 PackageData packageData = PackageWrapperUtil.getPackageInfoById(csarId);
505 if(null == packageData) {
506 return Response.status(Response.Status.PRECONDITION_FAILED).build();
509 handleDelayExec(operId);
511 OnBoardingResult oOnBoardingResult = FunctionTestHook.getOnBoardingResult(packageData);
512 if(null == oOnBoardingResult) {
513 return Response.status(Response.Status.PRECONDITION_FAILED).build();
515 filterOnBoardingResultByOperId(oOnBoardingResult, operId);
517 String strResult = ToolUtil.objectToString(oOnBoardingResult);
518 LOG.info("getOnBoardingResult response : " + strResult);
519 return Response.ok(strResult, "application/json").build();
520 } catch(NullPointerException e) {
521 LOG.error("Null param in getOnBoardingResult", e);
522 return Response.status(Response.Status.BAD_REQUEST).build();
526 private void filterOnBoardingResultByOperId(OnBoardingResult oOnBoardingResult, String operId) {
527 if(0 == operId.compareToIgnoreCase("all")) {
530 if(0 == operId.compareToIgnoreCase("download")) {
531 List<OnBoardingOperResult> operResultListTemp = new ArrayList<>();
532 OnBoardingOperResult operResultListTmp = new OnBoardingOperResult();
533 operResultListTmp.setOperId("download");
534 operResultListTmp.setStatus(0);
535 operResultListTemp.add(operResultListTmp);
536 oOnBoardingResult.setOperResult(operResultListTemp);
539 List<OnBoardingOperResult> operResultListOut = new ArrayList<>();
540 List<OnBoardingOperResult> operResultList = oOnBoardingResult.getOperResult();
541 for(OnBoardingOperResult operResult : operResultList) {
542 if(0 == operResult.getOperId().compareToIgnoreCase(operId)) {
543 operResultListOut.add(operResult);
546 oOnBoardingResult.setOperResult(operResultListOut);
550 * Interface to get OnBoarding Status by Operation ID
556 public Response getOperResultByOperTypeId(String csarId, String operTypeId) {
557 LOG.error("getOnBoardingResult request : csarId:" + csarId + " operTypeId:" + operTypeId);
558 if(null == csarId || null == operTypeId || csarId.isEmpty() || operTypeId.isEmpty()) {
559 return Response.status(Status.BAD_REQUEST).build();
562 PackageData packageData = PackageWrapperUtil.getPackageInfoById(csarId);
563 if(null == packageData) {
564 LOG.error("Failed to find package for PackageID:" + csarId);
565 return Response.status(Status.PRECONDITION_FAILED).build();
568 // Get result key to fetch Function Test Results
569 // ---------------------------------------------
570 String strResult = FunctionTestHook.getFuncTestResults(packageData);
571 if(null == strResult) {
572 LOG.error("NULL reponse for getOperResultByOperTypeId response :" + strResult);
573 return Response.status(Status.INTERNAL_SERVER_ERROR).build();
575 LOG.info("getOperResultByOperTypeId response :" + strResult);
576 return Response.ok(strResult, MediaType.APPLICATION_JSON).build();
579 private boolean handleDataValidate(String packageId, InputStream uploadedInputStream,
580 FormDataContentDisposition fileDetail) {
581 boolean bvalidateOk = false;
582 if((null != uploadedInputStream) && (fileDetail != null) && !ToolUtil.isEmptyString(packageId)) {
589 * Interface to get OnBoarding Steps
593 public Response getOnBoardingSteps() {
594 LOG.info("Get OnBoarding Steps request Received !!!");
596 String filePath = org.onap.vnfsdk.marketplace.filemanage.http.ToolUtil.getAppDeployPath() + File.separator
597 + "generalconfig/OnBoardingSteps.json";
598 LOG.info("Onboarding Steps Json file Path :" + filePath);
600 OnBoardingSteps oOnBoardingSteps =
601 (OnBoardingSteps)FileUtil.readJsonDatafFromFile(filePath, OnBoardingSteps.class);
602 if(null == oOnBoardingSteps) {
603 return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
605 String strResult = ToolUtil.objectToString(oOnBoardingSteps);
606 LOG.info("getOnBoardingSteps response :" + strResult);
607 return Response.ok(strResult, MediaType.APPLICATION_JSON).build();
610 private void handleDelayExec(String operId) {
611 if(0 == operId.compareToIgnoreCase(CommonConstant.functionTest.FUNCTEST_EXEC)) {
614 } catch(InterruptedException e) {
615 LOG.info("handleDelayExex response : ", e);
616 Thread.currentThread().interrupt();