CLEANED UP IMPORTS IN MSO-VFNM-ETSI Adapter
[so.git] / adapters / mso-vnfm-adapter / mso-vnfm-etsi-adapter / src / main / java / org / onap / so / adapters / vnfmadapter / extclients / SdcPackageProvider.java
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2019 Nordix Foundation.
4  * ================================================================================
5  *  Modifications Copyright (c) 2019 Samsung
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  * SPDX-License-Identifier: Apache-2.0
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.so.adapters.vnfmadapter.extclients;
24
25 import com.google.common.io.ByteStreams;
26 import com.google.gson.Gson;
27 import com.google.gson.JsonObject;
28 import org.apache.commons.codec.binary.Base64;
29 import org.apache.http.HttpEntity;
30 import org.apache.http.client.methods.CloseableHttpResponse;
31 import org.apache.http.client.methods.HttpGet;
32 import org.apache.http.impl.client.CloseableHttpClient;
33 import org.apache.http.impl.client.HttpClients;
34 import org.onap.so.utils.CryptoUtils;
35 import org.slf4j.Logger;
36 import org.springframework.beans.factory.annotation.Value;
37 import org.springframework.stereotype.Component;
38 import org.yaml.snakeyaml.Yaml;
39 import java.io.ByteArrayInputStream;
40 import java.io.ByteArrayOutputStream;
41 import java.io.IOException;
42 import java.io.InputStream;
43 import java.nio.charset.StandardCharsets;
44 import java.util.HashSet;
45 import java.util.Iterator;
46 import java.util.List;
47 import java.util.NoSuchElementException;
48 import java.util.Set;
49 import java.util.zip.ZipEntry;
50 import java.util.zip.ZipInputStream;
51 import static com.google.common.base.Splitter.on;
52 import static com.google.common.collect.Iterables.filter;
53 import static com.google.common.io.ByteStreams.toByteArray;
54 import static java.lang.String.format;
55 import static org.apache.http.HttpHeaders.ACCEPT;
56 import static org.apache.http.HttpHeaders.AUTHORIZATION;
57 import static org.onap.so.adapters.vnfmadapter.NvfmAdapterUtils.abortOperation;
58 import static org.onap.so.adapters.vnfmadapter.NvfmAdapterUtils.child;
59 import static org.onap.so.adapters.vnfmadapter.NvfmAdapterUtils.childElement;
60 import static org.onap.so.adapters.vnfmadapter.NvfmAdapterUtils.children;
61 import static org.slf4j.LoggerFactory.getLogger;
62 import static org.springframework.http.MediaType.APPLICATION_OCTET_STREAM_VALUE;
63
64 @Component
65 public class SdcPackageProvider {
66     private static final String GET_PACKAGE_URL = "%s/catalog/resources/%s/toscaModel";
67     @Value("${sdc.toscametapath:TOSCA-Metadata/TOSCA.meta}")
68     private List<String> toscaMetaPaths;
69     private final String TOSCA_VNFD_KEY = "Entry-Definitions";
70     private static Logger logger = getLogger(SdcPackageProvider.class);
71
72     @Value("${sdc.username}")
73     private String sdcUsername;
74     @Value("${sdc.password}")
75     private String sdcPassword;
76     @Value("${sdc.key}")
77     private String sdcKey;
78     @Value("${sdc.endpoint}")
79     private String baseUrl;
80
81     public String getVnfdId(String csarId) {
82         return getVnfNodeProperty(csarId, "descriptor_id");
83     }
84
85     private String getVnfNodeProperty(final String csarId, final String propertyName) {
86         logger.debug("Getting " + propertyName + " from " + csarId);
87         final byte[] onapPackage = getPackage(csarId);
88
89         try {
90             final String vnfdLocation = getVnfdLocation(new ByteArrayInputStream(onapPackage));
91             final String onapVnfdContent = getFileInZip(new ByteArrayInputStream(onapPackage), vnfdLocation).toString();
92             final JsonObject root = new Gson().toJsonTree(new Yaml().load(onapVnfdContent)).getAsJsonObject();
93
94             final JsonObject topologyTemplates = child(root, "topology_template");
95             final JsonObject nodeTemplates = child(topologyTemplates, "node_templates");
96             for (final JsonObject child : children(nodeTemplates)) {
97                 final String type = childElement(child, "type").getAsString();
98                 String propertyValue = null;
99                 if (type.equals("tosca.nodes.nfv.VNF")) {
100                     final JsonObject properties = child(child, "properties");
101                     logger.debug("properties: " + properties.toString());
102
103                     propertyValue = properties.get(propertyName).getAsJsonPrimitive().getAsString();
104                 }
105                 if (propertyValue == null) {
106                     propertyValue = getValueFromNodeTypeDefinition(root, type, propertyName);
107                 }
108                 return propertyValue;
109             }
110
111         } catch (final Exception e) {
112             throw new IllegalArgumentException("Unable to extract " + propertyName + " from ONAP package", e);
113         }
114         throw new IllegalArgumentException("Unable to extract " + propertyName + " from ONAP package");
115     }
116
117     private String getValueFromNodeTypeDefinition(final JsonObject root, final String nodeTypeName,
118             final String propertyName) {
119         final JsonObject nodeTypes = child(root, "node_types");
120         final JsonObject nodeType = child(nodeTypes, nodeTypeName);
121
122         if (childElement(nodeType, "derived_from").getAsString().equals("tosca.nodes.nfv.VNF")) {
123             final JsonObject properties = child(nodeType, "properties");
124             logger.debug("properties: " + properties.toString());
125             final JsonObject property = child(properties, propertyName);
126             logger.debug("property: " + property.toString());
127             logger.debug("property default: " + childElement(property, "default").toString());
128             return childElement(property, "default").getAsJsonPrimitive().getAsString();
129         }
130         return null;
131     }
132
133     private byte[] getPackage(String csarId) {
134         final String SERVICE_NAME = "vnfm-adapter";
135         try (CloseableHttpClient client = HttpClients.createDefault()) {
136             HttpGet httpget = new HttpGet(format(GET_PACKAGE_URL, baseUrl, csarId));
137             httpget.setHeader(ACCEPT, APPLICATION_OCTET_STREAM_VALUE);
138             httpget.setHeader("X-ECOMP-InstanceID", SERVICE_NAME);
139             httpget.setHeader("X-FromAppId", SERVICE_NAME);
140             String auth = sdcUsername + ":" + CryptoUtils.decrypt(sdcPassword, sdcKey);
141             byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(StandardCharsets.ISO_8859_1));
142             String authHeader = "Basic " + new String(encodedAuth);
143             httpget.setHeader(AUTHORIZATION, authHeader);
144             logger.debug("Fetching from SDC: " + httpget);
145             CloseableHttpResponse response = client.execute(httpget);
146             HttpEntity entity = response.getEntity();
147             InputStream is = entity.getContent();
148             byte[] bytes = toByteArray(is);
149             return bytes;
150         } catch (Exception e) {
151             throw abortOperation("Unable to download " + csarId + " package from SDC", e);
152         }
153     }
154
155     private String getVnfdLocation(InputStream stream) throws IOException {
156         Iterator pathIterator = toscaMetaPaths.iterator();
157         while (pathIterator.hasNext()) {
158             String toscaMetadata = new String(getFileInZip(stream, pathIterator.next().toString()).toByteArray());
159             if (!toscaMetadata.isEmpty()) {
160                 String toscaVnfdLine =
161                         filter(on("\n").split(toscaMetadata), line -> line.contains(TOSCA_VNFD_KEY)).iterator().next();
162                 return toscaVnfdLine.replace(TOSCA_VNFD_KEY + ":", "").trim();
163             }
164         }
165         throw abortOperation("Unable to find valid Tosca Path");
166     }
167
168     private static ByteArrayOutputStream getFileInZip(InputStream zip, String path) throws IOException {
169         ZipInputStream zipInputStream = new ZipInputStream(zip);
170         ByteArrayOutputStream fileContent = getFileInZip(zipInputStream, path);
171         zipInputStream.close();
172         return fileContent;
173     }
174
175     private static ByteArrayOutputStream getFileInZip(ZipInputStream zipInputStream, String path) throws IOException {
176         ZipEntry zipEntry;
177         Set<String> items = new HashSet<>();
178         while ((zipEntry = zipInputStream.getNextEntry()) != null) {
179             items.add(zipEntry.getName());
180             if (zipEntry.getName().matches(path)) {
181                 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
182                 ByteStreams.copy(zipInputStream, byteArrayOutputStream);
183                 return byteArrayOutputStream;
184             }
185         }
186         logger.error("Unable to find the {} in archive found: {}", path, items);
187         throw new NoSuchElementException("Unable to find the " + path + " in archive found: " + items);
188     }
189
190     public String getFlavourId(String csarId) {
191         return getVnfNodeProperty(csarId, "flavour_id");
192     }
193 }