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