2 * Copyright 2016-2017, Nokia Corporation
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm;
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;
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;
34 import java.util.zip.ZipEntry;
35 import java.util.zip.ZipInputStream;
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;
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
52 public class CatalogManager {
54 * The location of the CBAM package within the ONAP package
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;
64 CatalogManager(CbamRestApiProvider cbamRestApiProvider, IPackageProvider packageProvider) {
65 this.cbamRestApiProvider = cbamRestApiProvider;
66 this.packageProvider = packageProvider;
71 * @param path the path of the file to be returned
72 * @return the file in the zip
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();
82 * @param stream the CBAM VNF package
83 * @return the location of the VNFD within the CBAM package
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();
91 private static ByteArrayOutputStream getFileInZip(ZipInputStream zipInputStream, String path) throws IOException {
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;
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);
107 * Prepare the VNF package in CBAM. If the package is not available in the catalog it is uploaded.
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
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)) {
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);
128 throw buildFatalFailure(logger, "Unable to create VNF with " + csarId + " CSAR identifier in package in CBAM", e);
132 return queryPackageFromCBAM(cbamVnfdId, cbamCatalogApi);
136 * Gets the content of the VNFD from the CBAM package uploaded to CBAM
138 * @param vnfmId the identifier of the VNFM
139 * @param vnfdId the identifier of the VNFD
140 * @return the content of the CBAM VNFD
142 public String getCbamVnfdContent(String vnfmId, String vnfdId) {
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);
152 private boolean isPackageReplicated(String cbamVnfdId, DefaultApi cbamCatalogApi) {
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);
160 private CatalogAdapterVnfpackage queryPackageFromCBAM(String cbamVnfdId, DefaultApi cbamCatalogApi) {
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);
168 private boolean isPackageReplicatedToCbam(String cbamVnfdId, DefaultApi cbamCatalogApi) throws IOException {
169 for (CatalogAdapterVnfpackage vnfPackage : cbamCatalogApi.list().execute().body()) {
170 if (vnfPackage.getVnfdId().equals(cbamVnfdId)) {