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