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