d779bf5f3dd0da411038d094fde5a8d3555a4e7c
[vnfsdk/refrepo.git] /
1 /**
2  * Copyright 2017 Huawei Technologies Co., Ltd.
3  *
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
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 package org.onap.vnfsdk.marketplace.wrapper;
18
19 import java.io.BufferedInputStream;
20 import java.io.File;
21 import java.io.FileInputStream;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.concurrent.Callable;
27 import java.util.concurrent.ExecutorService;
28 import java.util.concurrent.Executors;
29
30 import javax.ws.rs.core.HttpHeaders;
31 import javax.ws.rs.core.MediaType;
32 import javax.ws.rs.core.Response;
33 import javax.ws.rs.core.Response.Status;
34
35 import org.apache.commons.io.IOUtils;
36 import org.apache.commons.lang3.StringUtils;
37 import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
38 import org.onap.validation.csar.CsarValidator;
39 import org.onap.vnfsdk.marketplace.common.CommonConstant;
40 import org.onap.vnfsdk.marketplace.common.FileUtil;
41 import org.onap.vnfsdk.marketplace.common.JsonUtil;
42 import org.onap.vnfsdk.marketplace.common.RestUtil;
43 import org.onap.vnfsdk.marketplace.common.ToolUtil;
44 import org.onap.vnfsdk.marketplace.db.entity.PackageData;
45 import org.onap.vnfsdk.marketplace.db.exception.MarketplaceResourceException;
46 import org.onap.vnfsdk.marketplace.db.resource.PackageManager;
47 import org.onap.vnfsdk.marketplace.db.util.MarketplaceDbUtil;
48 import org.onap.vnfsdk.marketplace.entity.request.PackageBasicInfo;
49 import org.onap.vnfsdk.marketplace.entity.response.PackageMeta;
50 import org.onap.vnfsdk.marketplace.entity.response.UploadPackageResponse;
51 import org.onap.vnfsdk.marketplace.filemanage.FileManagerFactory;
52 import org.onap.vnfsdk.marketplace.onboarding.entity.OnBoardingOperResult;
53 import org.onap.vnfsdk.marketplace.onboarding.entity.OnBoardingResult;
54 import org.onap.vnfsdk.marketplace.onboarding.entity.OnBoardingSteps;
55 import org.onap.vnfsdk.marketplace.onboarding.entity.OnBoradingRequest;
56 import org.onap.vnfsdk.marketplace.onboarding.hooks.functiontest.FunctionTestExceutor;
57 import org.onap.vnfsdk.marketplace.onboarding.hooks.functiontest.FunctionTestHook;
58 import org.onap.vnfsdk.marketplace.onboarding.hooks.validatelifecycle.ValidateLifecycleTestResponse;
59 import org.onap.vnfsdk.marketplace.onboarding.onboardmanager.OnBoardingHandler;
60 import org.slf4j.Logger;
61 import org.slf4j.LoggerFactory;
62
63 public class PackageWrapper {
64
65     private static PackageWrapper packageWrapper;
66
67     private static final Logger LOG = LoggerFactory.getLogger(PackageWrapper.class);
68
69     /**
70      * get PackageWrapper instance.
71      * 
72      * @return package wrapper instance
73      */
74     public static PackageWrapper getInstance() {
75         if(packageWrapper == null) {
76             packageWrapper = new PackageWrapper();
77         }
78         return packageWrapper;
79     }
80
81     public Response updateValidateStatus(InputStream inputStream) throws IOException {
82         String reqParam = IOUtils.toString(inputStream);
83         LOG.info("updateValidateStatus request param:" + reqParam);
84         if(StringUtils.isBlank(reqParam)) {
85             LOG.error("The updateValidateStatus request params can't be null");
86             return Response.status(Status.EXPECTATION_FAILED).build();
87         }
88
89         ValidateLifecycleTestResponse lyfValidateResp =
90                 JsonUtil.fromJson(reqParam, ValidateLifecycleTestResponse.class);
91         if(!checkOperationSucess(lyfValidateResp)) {
92             return Response.status(Status.EXPECTATION_FAILED).build();
93         }
94
95         String funcTestResponse = FunctionTestExceutor.executeFunctionTest(reqParam);
96         if(null == funcTestResponse) {
97             return Response.status(Status.EXPECTATION_FAILED).build();
98         }
99
100         if(!funcTestResponse.contains(CommonConstant.SUCCESS_STR)) {
101             return Response.status(Status.EXPECTATION_FAILED).build();
102         }
103
104         return Response.ok().build();
105     }
106
107     private boolean checkOperationSucess(ValidateLifecycleTestResponse lyfValidateResp) {
108         boolean bOperStatus = false;
109         if(null == lyfValidateResp) {
110             LOG.error("ValidateLifecycleTestResponse  is NUll !!!");
111             return bOperStatus;
112         }
113         if(lyfValidateResp.getLifecycle_status().equalsIgnoreCase(CommonConstant.SUCCESS_STR)
114                 && lyfValidateResp.getValidate_status().equalsIgnoreCase(CommonConstant.SUCCESS_STR)) {
115             LOG.error("Lifecycle/Validation Response failed :" + lyfValidateResp.getLifecycle_status() + File.separator
116                     + lyfValidateResp.getValidate_status());
117             bOperStatus = true;
118         }
119         return bOperStatus;
120     }
121
122     /**
123      * query package list by condition.
124      * 
125      * @param name package name
126      * @param provider package provider
127      * @param version package version
128      * @param deletionPending package deletionPending
129      * @param type package type
130      * @return Response
131      */
132     public Response queryPackageListByCond(String name, String provider, String version, String deletionPending,
133             String type) {
134         List<PackageData> dbresult = new ArrayList<>();
135         List<PackageMeta> result = new ArrayList<>();
136         LOG.info("query package info.name:" + name + " provider:" + provider + " version" + version + " deletionPending"
137                 + deletionPending + " type:" + type);
138         try {
139             dbresult = PackageManager.getInstance().queryPackage(name, provider, version, deletionPending, type);
140             result = PackageWrapperUtil.packageDataList2PackageMetaList(dbresult);
141             return Response.ok(ToolUtil.objectToString(result)).build();
142         } catch(MarketplaceResourceException e1) {
143             LOG.error("query package by csarId from db error ! ", e1);
144             return RestUtil.getRestException(e1.getMessage());
145         }
146     }
147
148     /**
149      * query package by id.
150      * 
151      * @param csarId package id
152      * @return Response
153      */
154     public Response queryPackageById(String csarId) {
155         PackageData dbResult = PackageWrapperUtil.getPackageInfoById(csarId);
156         PackageMeta result = PackageWrapperUtil.packageData2PackageMeta(dbResult);
157         return Response.ok(ToolUtil.objectToString(result)).build();
158     }
159
160     /**
161      * upload package.
162      * 
163      * @param uploadedInputStream inputStream
164      * @param fileDetail package detail
165      * @param head http header
166      * @return Response
167      * @throws Exception e
168      */
169     public Response uploadPackage(InputStream uploadedInputStream, FormDataContentDisposition fileDetail,
170             String details, HttpHeaders head) throws MarketplaceResourceException {
171         LOG.info("Upload/Reupload request Received !!!!");
172         try {
173             String packageId = MarketplaceDbUtil.generateId();
174             return handlePackageUpload(packageId, uploadedInputStream, fileDetail, details, head);
175         } catch(IOException e) {
176             LOG.error("can't get package id", e);
177         }
178         return Response.status(Status.INTERNAL_SERVER_ERROR).build();
179     }
180
181     private UploadPackageResponse manageUpload(String packageId, String fileName, String fileLocation, String details,
182             String contentRange) throws IOException, MarketplaceResourceException {
183         String localDirName = ToolUtil.getTempDir(CommonConstant.CATALOG_CSAR_DIR_NAME, fileName);
184         PackageBasicInfo basicInfo = PackageWrapperUtil.getPacageBasicInfo(fileLocation);
185         UploadPackageResponse result = new UploadPackageResponse();
186         Boolean isEnd = PackageWrapperUtil.isUploadEnd(contentRange);
187         if(isEnd) {
188             PackageMeta packageMeta =
189                     PackageWrapperUtil.getPackageMeta(packageId, fileName, fileLocation, basicInfo, details);
190             try {
191                 String path = basicInfo.getType().toString() + File.separator + basicInfo.getProvider() + File.separator
192                         + packageMeta.getCsarId() + File.separator + fileName.replace(".csar", "") + File.separator
193                         + basicInfo.getVersion();
194
195                 String dowloadUri = File.separator + path + File.separator;
196                 packageMeta.setDownloadUri(dowloadUri);
197
198                 LOG.info("dest path is : " + path);
199                 LOG.info("packageMeta = " + ToolUtil.objectToString(packageMeta));
200
201                 PackageData packageData = PackageWrapperUtil.getPackageData(packageMeta);
202
203                 String destPath = File.separator + path + File.separator + File.separator;
204                 boolean uploadResult = FileManagerFactory.createFileManager().upload(localDirName, destPath);
205                 if(uploadResult) {
206                     OnBoradingRequest oOnboradingRequest = new OnBoradingRequest();
207                     oOnboradingRequest.setCsarId(packageId);
208                     oOnboradingRequest.setPackageName(fileName);
209                     oOnboradingRequest.setPackagePath(localDirName);
210
211                     packageData.setCsarId(packageId);
212                     packageData.setDownloadCount(-1);
213                     PackageData packateDbData = PackageManager.getInstance().addPackage(packageData);
214
215                     LOG.info("Store package data to database succed ! packateDbData = "
216                             + ToolUtil.objectToString(packateDbData));
217                     LOG.info("upload package file end, fileName:" + fileName);
218
219                     result.setCsarId(packateDbData.getCsarId());
220
221                     addOnBoardingRequest(oOnboradingRequest);
222
223                     LOG.info("OnboradingRequest Data : " + ToolUtil.objectToString(oOnboradingRequest));
224                 }
225             } catch(NullPointerException e) {
226                 LOG.error("Package basicInfo is incorrect ! basicIonfo = " + ToolUtil.objectToString(basicInfo), e);
227                 return null;
228             }
229         }
230         return result;
231     }
232
233     /**
234      * Interface for Uploading package
235      * 
236      * @param packageId
237      * @param uploadedInputStream
238      * @param fileDetail
239      * @param details
240      * @param head
241      * @return
242      * @throws IOException
243      * @throws MarketplaceResourceException
244      */
245     private Response handlePackageUpload(String packageId, InputStream uploadedInputStream,
246             FormDataContentDisposition fileDetail, String details, HttpHeaders head)
247             throws IOException, MarketplaceResourceException {
248         boolean bResult = handleDataValidate(packageId, uploadedInputStream, fileDetail);
249         if(!bResult) {
250             LOG.error("Validation of Input received for Package Upload failed !!!");
251             return Response.status(Status.EXPECTATION_FAILED).build();
252         }
253
254         String fileName = "temp_" + packageId + ".csar";
255         if(null != fileDetail) {
256             LOG.info("the fileDetail = " + ToolUtil.objectToString(fileDetail));
257
258             fileName = ToolUtil.processFileName(fileDetail.getFileName());
259         }
260
261         String localDirName = ToolUtil.getTempDir(CommonConstant.CATALOG_CSAR_DIR_NAME, fileName);
262
263         String contentRange = null;
264         if(head != null) {
265             contentRange = head.getHeaderString(CommonConstant.HTTP_HEADER_CONTENT_RANGE);
266         }
267         LOG.info("store package chunk file, fileName:" + fileName + ",contentRange:" + contentRange);
268         if(ToolUtil.isEmptyString(contentRange)) {
269             int fileSize = uploadedInputStream.available();
270             contentRange = "0-" + fileSize + "/" + fileSize;
271         }
272
273         String fileLocation = ToolUtil.storeChunkFileInLocal(localDirName, fileName, uploadedInputStream);
274         LOG.info("the fileLocation when upload package is :" + fileLocation);
275
276         uploadedInputStream.close();
277
278         try {
279             CsarValidator cv = new CsarValidator(packageId, fileLocation);
280
281             if(!cv.validateCsar()) {
282                 LOG.error("Could not validate failed");
283                 return Response.status(Status.EXPECTATION_FAILED).build();
284             }
285         } catch(Exception e) {
286             LOG.error("CSAR validation panicked", e);
287             return Response.status(Status.EXPECTATION_FAILED).build();
288         }
289
290         UploadPackageResponse result = manageUpload(packageId, fileName, fileLocation, details, contentRange);
291         if(null != result) {
292             return Response.ok(ToolUtil.objectToString(result), MediaType.APPLICATION_JSON).build();
293         } else {
294             return Response.serverError().build();
295         }
296     }
297
298     /**
299      * Execute OnBarding request
300      * 
301      * @param oOnboradingRequest
302      */
303     private void addOnBoardingRequest(final OnBoradingRequest oOnboradingRequest) {
304         ExecutorService es = Executors.newFixedThreadPool(CommonConstant.ONBOARDING_THREAD_COUNT);
305         Callable<Integer> callableInteger = () -> {
306             new OnBoardingHandler().handleOnBoardingReq(oOnboradingRequest);
307             return CommonConstant.SUCESS;
308         };
309         es.submit(callableInteger);
310     }
311
312     /**
313      * delete package by package id.
314      * 
315      * @param csarId package id
316      * @return Response
317      */
318     public Response delPackage(String csarId) {
319         LOG.info("delete package  info.csarId:" + csarId);
320         if(ToolUtil.isEmptyString(csarId)) {
321             LOG.error("delete package  fail, csarid is null");
322             return Response.serverError().build();
323         }
324         deletePackageDataById(csarId);
325         return Response.ok().build();
326     }
327
328     /**
329      * Delete Package by CSAR ID
330      * 
331      * @param csarId
332      */
333     private void deletePackageDataById(String csarId) {
334         String packagePath = PackageWrapperUtil.getPackagePath(csarId);
335         if(packagePath == null) {
336             LOG.error("package path is null! ");
337         }
338
339         // Delete Package
340         FileManagerFactory.createFileManager().delete(packagePath);
341         // Delete Results Data
342         FileManagerFactory.createFileManager().delete(File.separator + csarId);
343
344         // delete package data from database
345         try {
346             PackageManager.getInstance().deletePackage(csarId);
347         } catch(MarketplaceResourceException e1) {
348             LOG.error("delete package  by csarId from db error ! " + e1.getMessage(), e1);
349         }
350     }
351
352     /**
353      * download package by package id.
354      * 
355      * @param csarId package id
356      * @return Response
357      */
358     public Response downloadCsarPackagesById(String csarId) {
359         PackageData packageData = PackageWrapperUtil.getPackageInfoById(csarId);
360
361         String packageName = packageData.getName();
362         String path = org.onap.vnfsdk.marketplace.filemanage.http.ToolUtil.getHttpServerAbsolutePath()
363                 + File.separatorChar + packageData.getType() + File.separatorChar + packageData.getProvider()
364                 + File.separatorChar + packageData.getCsarId() + File.separator + packageName + File.separatorChar
365                 + packageData.getVersion() + File.separator + packageName + ".csar";
366
367         LOG.info("downloadCsarPackagesById path is :  " + path);
368
369         File csarFile = new File(path);
370         if(!csarFile.exists()) {
371             return Response.status(Status.INTERNAL_SERVER_ERROR).build();
372         }
373
374         LOG.info("downloadCsarPackagesById ABS path is :  " + csarFile.getAbsolutePath());
375
376         try {
377             InputStream fis = new BufferedInputStream(new FileInputStream(csarFile.getAbsolutePath()));
378             return Response.ok(fis).header("Content-Disposition", "attachment; filename=\"" + csarFile.getName() + "\"")
379                     .build();
380         } catch(Exception e1) {
381             LOG.error("download vnf package fail.", e1);
382             return RestUtil.getRestException(e1.getMessage());
383         }
384     }
385
386     /**
387      * get package file uri.
388      * 
389      * @param csarId package id
390      * @param relativePath file relative path
391      * @return Response
392      */
393     public Response getCsarFileUri(String csarId) {
394         return downloadCsarPackagesById(csarId);
395     }
396
397     /**
398      * Interface to Update Download count for CSAR ID
399      * 
400      * @param csarId
401      * @return
402      */
403     public Response updateDwonloadCount(String csarId) {
404         return handleDownladCountUpdate(csarId) ? Response.ok().build()
405                 : Response.status(Status.EXPECTATION_FAILED).build();
406     }
407
408     /**
409      * Handle downlowa count update
410      * 
411      * @param csarId
412      * @return
413      */
414     private boolean handleDownladCountUpdate(String csarId) {
415         boolean bupdateSucess = false;
416         try {
417             PackageManager.getInstance().updateDownloadCount(csarId);
418             bupdateSucess = true;
419         } catch(Exception exp) {
420             LOG.error("Updating Donwload count failed for Package with ID !!! : " + exp.getMessage(), exp);
421         }
422         return bupdateSucess;
423     }
424
425     /**
426      * Interface to Re upload Package
427      * 
428      * @param csarId
429      * @param uploadedInputStream
430      * @param fileDetail
431      * @param details
432      * @param head
433      * @return
434      * @throws Exception
435      */
436     public Response reUploadPackage(String csarId, InputStream uploadedInputStream,
437             FormDataContentDisposition fileDetail, String details, HttpHeaders head)
438             throws MarketplaceResourceException {
439         LOG.info("Reupload request Received !!!!");
440
441         // STEP 1: Validate Input Data
442         // ----------------------------
443         boolean bResult = handleDataValidate(csarId, uploadedInputStream, fileDetail);
444         if(!bResult) {
445             LOG.error("Validation of Input received for Package Upload failed during Reload!!!");
446             return Response.status(Status.EXPECTATION_FAILED).build();
447         }
448
449         try {
450             // STEP 2: Delete All Package Data based on package id
451             // ----------------------------------------------------
452             deletePackageDataById(csarId);
453
454             // STEP 3: upload package with same package id
455             // -------------------------------------------
456             return handlePackageUpload(csarId, uploadedInputStream, fileDetail, details, head);
457         } catch(IOException e) {
458             LOG.error("delete package failed", e);
459         }
460         return Response.status(Status.INTERNAL_SERVER_ERROR).build();
461     }
462
463     /**
464      * Interface to get OnBoarding Result by Operation Type
465      * 
466      * @param csarId
467      * @param operTypeId
468      * @param operId
469      * @return
470      */
471     public Response getOnBoardingResult(String csarId, String operTypeId, String operId) {
472         LOG.info("getOnBoardingResult request : csarId:" + csarId + " operTypeId:" + operTypeId + " operId:" + operId);
473         try {
474             PackageData packageData = PackageWrapperUtil.getPackageInfoById(csarId);
475             if(null == packageData) {
476                 return Response.status(Response.Status.PRECONDITION_FAILED).build();
477             }
478
479             handleDelayExec(operId);
480
481             OnBoardingResult oOnBoardingResult = FunctionTestHook.getOnBoardingResult(packageData);
482             if(null == oOnBoardingResult) {
483                 return Response.status(Response.Status.PRECONDITION_FAILED).build();
484             }
485             filterOnBoardingResultByOperId(oOnBoardingResult, operId);
486
487             String strResult = ToolUtil.objectToString(oOnBoardingResult);
488             LOG.info("getOnBoardingResult response : " + strResult);
489             return Response.ok(strResult, "application/json").build();
490         } catch(NullPointerException e) {
491             LOG.error("Null param in getOnBoardingResult", e);
492             return Response.status(Response.Status.BAD_REQUEST).build();
493         }
494     }
495
496     private void filterOnBoardingResultByOperId(OnBoardingResult oOnBoardingResult, String operId) {
497         if(0 == operId.compareToIgnoreCase("all")) {
498             return;
499         }
500         if(0 == operId.compareToIgnoreCase("download")) {
501             List<OnBoardingOperResult> operResultListTemp = new ArrayList<>();
502             OnBoardingOperResult operResultListTmp = new OnBoardingOperResult();
503             operResultListTmp.setOperId("download");
504             operResultListTmp.setStatus(0);
505             operResultListTemp.add(operResultListTmp);
506             oOnBoardingResult.setOperResult(operResultListTemp);
507             return;
508         }
509         List<OnBoardingOperResult> operResultListOut = new ArrayList<>();
510         List<OnBoardingOperResult> operResultList = oOnBoardingResult.getOperResult();
511         for(OnBoardingOperResult operResult : operResultList) {
512             if(0 == operResult.getOperId().compareToIgnoreCase(operId)) {
513                 operResultListOut.add(operResult);
514             }
515         }
516         oOnBoardingResult.setOperResult(operResultListOut);
517     }
518
519     /**
520      * Interface to get OnBoarding Status by Operation ID
521      * 
522      * @param csarId
523      * @param operTypeId
524      * @return
525      */
526     public Response getOperResultByOperTypeId(String csarId, String operTypeId) {
527         LOG.error("getOnBoardingResult request : csarId:" + csarId + " operTypeId:" + operTypeId);
528         if(null == csarId || null == operTypeId || csarId.isEmpty() || operTypeId.isEmpty()) {
529             return Response.status(Status.BAD_REQUEST).build();
530         }
531
532         PackageData packageData = PackageWrapperUtil.getPackageInfoById(csarId);
533         if(null == packageData) {
534             LOG.error("Failed to find package for PackageID:" + csarId);
535             return Response.status(Status.PRECONDITION_FAILED).build();
536         }
537
538         // Get result key to fetch Function Test Results
539         // ---------------------------------------------
540         String strResult = FunctionTestHook.getFuncTestResults(packageData);
541         if(null == strResult) {
542             LOG.error("NULL reponse for getOperResultByOperTypeId response :" + strResult);
543             return Response.status(Status.INTERNAL_SERVER_ERROR).build();
544         }
545         LOG.info("getOperResultByOperTypeId response :" + strResult);
546         return Response.ok(strResult, MediaType.APPLICATION_JSON).build();
547     }
548
549     private boolean handleDataValidate(String packageId, InputStream uploadedInputStream,
550             FormDataContentDisposition fileDetail) {
551         boolean bvalidateOk = false;
552         if((null != uploadedInputStream) && (fileDetail != null) && !ToolUtil.isEmptyString(packageId)) {
553             bvalidateOk = true;
554         }
555         return bvalidateOk;
556     }
557
558     /**
559      * Interface to get OnBoarding Steps
560      * 
561      * @return
562      */
563     public Response getOnBoardingSteps() {
564         LOG.info("Get OnBoarding Steps request Received !!!");
565
566         String filePath = org.onap.vnfsdk.marketplace.filemanage.http.ToolUtil.getAppDeployPath() + File.separator
567                 + "generalconfig/OnBoardingSteps.json";
568         LOG.info("Onboarding Steps Json file Path  :" + filePath);
569
570         OnBoardingSteps oOnBoardingSteps =
571                 (OnBoardingSteps)FileUtil.readJsonDatafFromFile(filePath, OnBoardingSteps.class);
572         if(null == oOnBoardingSteps) {
573             return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
574         }
575         String strResult = ToolUtil.objectToString(oOnBoardingSteps);
576         LOG.info("getOnBoardingSteps response :" + strResult);
577         return Response.ok(strResult, MediaType.APPLICATION_JSON).build();
578     }
579
580     private void handleDelayExec(String operId) {
581         if(0 == operId.compareToIgnoreCase(CommonConstant.functionTest.FUNCTEST_EXEC)) {
582             try {
583                 Thread.sleep(8000);
584             } catch(InterruptedException e) {
585                 LOG.info("handleDelayExex response : ", e);
586                 Thread.currentThread().interrupt();
587             }
588         }
589     }
590 }