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