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