3396d7651505de3ecc323f4a7f85ab26c06d3510
[vfc/nfvo/driver/vnfm/svnfm.git] / nokiav2 / driver / src / main / java / org / onap / vfc / nfvo / driver / vnfm / svnfm / nokia / vnfm / CatalogManager.java
1 /*
2  * Copyright 2016-2017, Nokia Corporation
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.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm;
18
19 import com.google.common.io.ByteStreams;
20 import com.nokia.cbam.catalog.v1.ApiException;
21 import com.nokia.cbam.catalog.v1.api.DefaultApi;
22 import com.nokia.cbam.catalog.v1.model.CatalogAdapterVnfpackage;
23 import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.api.IPackageProvider;
24 import org.slf4j.Logger;
25 import org.springframework.beans.factory.annotation.Autowired;
26 import org.springframework.stereotype.Component;
27
28 import java.io.*;
29 import java.nio.file.Path;
30 import java.util.HashSet;
31 import java.util.NoSuchElementException;
32 import java.util.Set;
33 import java.util.zip.ZipEntry;
34 import java.util.zip.ZipInputStream;
35
36 import static com.google.common.base.Splitter.on;
37 import static com.google.common.collect.Iterables.filter;
38 import static java.nio.file.Files.createTempFile;
39 import static java.nio.file.Files.write;
40 import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.fatalFailure;
41 import static org.slf4j.LoggerFactory.getLogger;
42
43
44 /**
45  * Responsible for handling the CBAM catalog
46  * - the VNF package is uploaded as part of the instantiation
47  * - the VNF package is not deleted after VNF deletion
48  */
49 @Component
50 public class CatalogManager {
51     /**
52      * The location of the CBAM package within the ONAP package
53      */
54     public static final String CBAM_PACKAGE_NAME_IN_ZIP = "Artifacts/Deployment/OTHER/cbam.package.zip";
55     private static final String TOSCA_META_PATH = "TOSCA-Metadata/TOSCA.meta";
56     private static final String TOSCA_VNFD_KEY = "Entry-Definitions";
57     private static Logger logger = getLogger(CatalogManager.class);
58     private final CbamRestApiProvider cbamRestApiProvider;
59     private final IPackageProvider packageProvider;
60
61     @Autowired
62     CatalogManager(CbamRestApiProvider cbamRestApiProvider, IPackageProvider packageProvider) {
63         this.cbamRestApiProvider = cbamRestApiProvider;
64         this.packageProvider = packageProvider;
65     }
66
67     /**
68      * @param zip  the zip
69      * @param path the path of the file to be returned
70      * @return the file in the zip
71      */
72     public static ByteArrayOutputStream getFileInZip(InputStream zip, String path) throws IOException {
73         ZipInputStream zipInputStream = new ZipInputStream(zip);
74         ByteArrayOutputStream fileContent = getFileInZip(zipInputStream, path);
75         zipInputStream.close();
76         return fileContent;
77     }
78
79     /**
80      * @param stream the CBAM VNF package
81      * @return the location of the VNFD within the CBAM package
82      */
83     public static String getVnfdLocation(InputStream stream) throws IOException {
84         String toscaMetadata = new String(getFileInZip(stream, TOSCA_META_PATH).toByteArray());
85         String toscaVnfdLine = filter(on("\n").split(toscaMetadata), line -> line.contains(TOSCA_VNFD_KEY)).iterator().next();
86         return toscaVnfdLine.replace(TOSCA_VNFD_KEY + ":", "").trim();
87     }
88
89     private static ByteArrayOutputStream getFileInZip(ZipInputStream zipInputStream, String path) throws IOException {
90         ZipEntry zipEntry;
91         Set<String> items = new HashSet<>();
92         while ((zipEntry = zipInputStream.getNextEntry()) != null) {
93             items.add(zipEntry.getName());
94             if (zipEntry.getName().matches(path)) {
95                 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
96                 ByteStreams.copy(zipInputStream, byteArrayOutputStream);
97                 return byteArrayOutputStream;
98             }
99         }
100         logger.error("Unable to find the {} in archive found: {}", path, items);
101         throw new NoSuchElementException("Unable to find the " + path + " in archive found: " + items);
102     }
103
104     /**
105      * Prepare the VNF package in CBAM. If the package is not available in the catalog it is uploaded.
106      *
107      * @param vnfmId the identifier of the VNFM
108      * @param csarId the CSAR identifier of the package in ONAP catalog
109      * @return the package in CBAM catalog
110      */
111     public CatalogAdapterVnfpackage preparePackageInCbam(String vnfmId, String csarId) {
112         String cbamVnfdId = packageProvider.getCbamVnfdId(csarId);
113         DefaultApi cbamCatalogApi = cbamRestApiProvider.getCbamCatalogApi(vnfmId);
114         if (!isPackageReplicated(cbamVnfdId, cbamCatalogApi)) {
115             try {
116                 Path tempFile = createTempFile("cbam", "zip");
117                 ByteArrayOutputStream cbamPackage = getFileInZip(new ByteArrayInputStream(packageProvider.getPackage(csarId)), CBAM_PACKAGE_NAME_IN_ZIP);
118                 write(tempFile, cbamPackage.toByteArray());
119                 //FIXME delete file
120                 return cbamCatalogApi.create(tempFile.toFile());
121             } catch (Exception e) {
122                 logger.debug("Probably concurrent package uploads", e);
123                 //retest if the VNF package exists in CBAM. It might happen that an other operation
124                 //triggered the replication making this API fail. The replication is considered to be
125                 //successful if the package exist in CBAM even if the current package transfer failed
126                 if (isPackageReplicated(cbamVnfdId, cbamCatalogApi)) {
127                     return queryPackageFromCBAM(cbamVnfdId, cbamCatalogApi);
128                 } else {
129                     throw fatalFailure(logger, "Unable to create VNF with " + csarId + " CSAR identifier in package in CBAM", e);
130                 }
131             }
132         }
133         return queryPackageFromCBAM(cbamVnfdId, cbamCatalogApi);
134     }
135
136     /**
137      * Gets the content of the VNFD from the CBAM package uploaded to CBAM
138      *
139      * @param vnfmId the identifier of the VNFM
140      * @param vnfdId the identifier of the VNFD
141      * @return the content of the CBAM VNFD
142      */
143     public String getCbamVnfdContent(String vnfmId, String vnfdId) {
144         try {
145             File content = cbamRestApiProvider.getCbamCatalogApi(vnfmId).content(vnfdId);
146             String vnfdPath = getVnfdLocation(new FileInputStream(content));
147             return new String(getFileInZip(new FileInputStream(content), vnfdPath).toByteArray());
148         } catch (Exception e) {
149             throw fatalFailure(logger, "Unable to get package with (" + vnfdId + ")", e);
150         }
151     }
152
153     private boolean isPackageReplicated(String cbamVnfdId, DefaultApi cbamCatalogApi) {
154         try {
155             return isPackageReplicatedToCbam(cbamVnfdId, cbamCatalogApi);
156         } catch (Exception e) {
157             throw fatalFailure(logger, "Unable to determine if the VNF package has been replicated in CBAM", e);
158         }
159     }
160
161     private CatalogAdapterVnfpackage queryPackageFromCBAM(String cbamVnfdId, DefaultApi cbamCatalogApi) {
162         try {
163             return cbamCatalogApi.getById(cbamVnfdId);
164         } catch (ApiException e) {
165             throw fatalFailure(logger, "Unable to query VNF package with " + cbamVnfdId + " from CBAM", e);
166         }
167     }
168
169     private boolean isPackageReplicatedToCbam(String cbamVnfdId, DefaultApi cbamCatalogApi) throws ApiException {
170         for (CatalogAdapterVnfpackage vnfPackage : cbamCatalogApi.list()) {
171             if (vnfPackage.getVnfdId().equals(cbamVnfdId)) {
172                 return true;
173             }
174         }
175         return false;
176     }
177 }