b224407ec827b537f1d0830dc33d781f918447ae
[aai/model-loader.git] / src / main / java / org / onap / aai / modelloader / entity / catalog / VnfCatalogArtifactHandler.java
1 /**\r
2  * ============LICENSE_START==========================================\r
3  * org.onap.aai\r
4  * ===================================================================\r
5  * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.\r
6  * Copyright © 2017-2018 Amdocs\r
7  * ===================================================================\r
8  * Licensed under the Apache License, Version 2.0 (the "License");\r
9  * you may not use this file except in compliance with the License.\r
10  * You may obtain a copy of the License at\r
11  *\r
12  *        http://www.apache.org/licenses/LICENSE-2.0\r
13  *\r
14  * Unless required by applicable law or agreed to in writing, software\r
15  * distributed under the License is distributed on an "AS IS" BASIS,\r
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
17  * See the License for the specific language governing permissions and\r
18  * limitations under the License.\r
19  * ============LICENSE_END============================================\r
20  */\r
21 package org.onap.aai.modelloader.entity.catalog;\r
22 \r
23 import com.google.gson.Gson;\r
24 import com.google.gson.reflect.TypeToken;\r
25 import java.io.UnsupportedEncodingException;\r
26 import java.util.List;\r
27 import java.util.Map;\r
28 import java.util.Map.Entry;\r
29 import java.util.UUID;\r
30 import javax.ws.rs.core.MediaType;\r
31 import javax.ws.rs.core.Response;\r
32 import org.apache.commons.text.StringEscapeUtils;\r
33 import org.onap.aai.cl.api.Logger;\r
34 import org.onap.aai.cl.eelf.LoggerFactory;\r
35 import org.onap.aai.modelloader.config.ModelLoaderConfig;\r
36 import org.onap.aai.modelloader.entity.Artifact;\r
37 import org.onap.aai.modelloader.entity.ArtifactHandler;\r
38 import org.onap.aai.modelloader.restclient.AaiRestClient;\r
39 import org.onap.aai.modelloader.service.ModelLoaderMsgs;\r
40 import org.onap.aai.restclient.client.OperationResult;\r
41 import org.springframework.web.util.UriUtils;\r
42 \r
43 /**\r
44  * VNF Catalog specific handling\r
45  */\r
46 public class VnfCatalogArtifactHandler extends ArtifactHandler {\r
47 \r
48     private static Logger logger = LoggerFactory.getInstance().getLogger(VnfCatalogArtifactHandler.class.getName());\r
49 \r
50     public static final String ATTR_UUID = "uuid";\r
51 \r
52     public VnfCatalogArtifactHandler(ModelLoaderConfig config) {\r
53         super(config);\r
54     }\r
55 \r
56     /*\r
57      * (non-Javadoc)\r
58      * \r
59      * @see org.openecomp.modelloader.entity.ArtifactHandler#pushArtifacts(java.util.List, java.lang.String)\r
60      */\r
61     @Override\r
62     public boolean pushArtifacts(List<Artifact> artifacts, String distributionId, List<Artifact> completedArtifacts,\r
63             AaiRestClient aaiClient) {\r
64         for (Artifact artifact : artifacts) {\r
65             try {\r
66                 distributeVnfcData(aaiClient, distributionId, artifact, completedArtifacts);\r
67             } catch (VnfImageException e) {\r
68                 if (e.getResultCode().isPresent()) {\r
69                     logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR,\r
70                             "Ingestion failed on vnf-image " + e.getImageId() + " with status "\r
71                                     + e.getResultCode().orElse(0) + ". Rolling back distribution.");\r
72                 } else {\r
73                     logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR,\r
74                             "Ingestion failed on " + e.getImageId() + ". Rolling back distribution.");\r
75                 }\r
76                 return false;\r
77             }\r
78         }\r
79 \r
80         return true;\r
81     }\r
82 \r
83     private void distributeVnfcData(AaiRestClient restClient, String distributionId, Artifact vnfcArtifact,\r
84             List<Artifact> completedArtifacts) throws VnfImageException {\r
85 \r
86         List<Map<String, String>> vnfcData = unmarshallVnfcData(vnfcArtifact);\r
87 \r
88         for (Map<String, String> dataItem : vnfcData) {\r
89             // If an empty dataItem is supplied, do nothing.\r
90             if (dataItem.isEmpty()) {\r
91                 logger.warn(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Empty image data supplied, skipping ingestion.");\r
92                 return;\r
93             }\r
94 \r
95             String urlParams;\r
96             StringBuilder imageId = new StringBuilder("vnf image");\r
97 \r
98             try {\r
99                 urlParams = buildUrlImgIdStrings(imageId, dataItem);\r
100             } catch (UnsupportedEncodingException e) {\r
101                 throw new VnfImageException(e);\r
102             }\r
103 \r
104             OperationResult tryGet =\r
105                     restClient.getResource(config.getAaiBaseUrl() + config.getAaiVnfImageUrl() + "?" + urlParams,\r
106                             distributionId, MediaType.APPLICATION_JSON_TYPE);\r
107 \r
108             if (tryGet == null) {\r
109                 throw new VnfImageException(imageId.toString());\r
110             }\r
111 \r
112             int resultCode = tryGet.getResultCode();\r
113             if (resultCode == Response.Status.NOT_FOUND.getStatusCode()) {\r
114                 // This vnf-image is missing, so add it\r
115                 boolean success = putVnfImage(restClient, dataItem, distributionId);\r
116                 if (!success) {\r
117                     throw new VnfImageException(imageId.toString());\r
118                 }\r
119                 completedArtifacts.add(vnfcArtifact);\r
120                 logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, imageId + " successfully ingested.");\r
121             } else if (resultCode == Response.Status.OK.getStatusCode()) {\r
122                 logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, imageId + " already exists. Skipping ingestion.");\r
123             } else {\r
124                 // if other than 404 or 200, something went wrong\r
125                 throw new VnfImageException(imageId.toString(), resultCode);\r
126             }\r
127         }\r
128     }\r
129 \r
130     private String buildUrlImgIdStrings(StringBuilder imageId, Map<String, String> dataItem)\r
131             throws UnsupportedEncodingException {\r
132         StringBuilder urlParams = new StringBuilder();\r
133         for (Entry<String, String> entry : dataItem.entrySet()) {\r
134             urlParams.append(entry.getKey()).append("=").append(UriUtils.encode(entry.getValue(), "UTF-8")).append("&");\r
135             imageId.append(" ").append(entry.getValue());\r
136         }\r
137         return urlParams.deleteCharAt(urlParams.length() - 1).toString();\r
138     }\r
139 \r
140     private boolean putVnfImage(AaiRestClient restClient, Map<String, String> dataItem, String distributionId) {\r
141         // Generate a new UUID for the image data item\r
142         String uuid = UUID.randomUUID().toString();\r
143         dataItem.put(ATTR_UUID, uuid);\r
144 \r
145         String payload = createVnfImagePayload(dataItem);\r
146         String putUrl = config.getAaiBaseUrl() + config.getAaiVnfImageUrl() + "/vnf-image/" + uuid;\r
147         OperationResult putResp =\r
148                 restClient.putResource(putUrl, payload, distributionId, MediaType.APPLICATION_JSON_TYPE);\r
149         return putResp != null && putResp.getResultCode() == Response.Status.CREATED.getStatusCode();\r
150     }\r
151 \r
152     private String createVnfImagePayload(Map<String, String> dataItem) {\r
153         dataItem.put(ATTR_UUID, UUID.randomUUID().toString());\r
154         return new Gson().toJson(dataItem);\r
155     }\r
156 \r
157     private List<Map<String, String>> unmarshallVnfcData(Artifact vnfcArtifact) {\r
158         // Unmarshall Babel JSON payload into a List of Maps of JSON attribute name/values.\r
159         return new Gson().fromJson(StringEscapeUtils.unescapeJson(vnfcArtifact.getPayload()),\r
160                 new TypeToken<List<Map<String, String>>>() {}.getType());\r
161     }\r
162 \r
163     /*\r
164      * If something fails in the middle of ingesting the catalog we want to roll back any changes to the DB\r
165      */\r
166     @Override\r
167     public void rollback(List<Artifact> completedArtifacts, String distributionId, AaiRestClient aaiClient) {\r
168         for (Artifact completedArtifact : completedArtifacts) {\r
169             List<Map<String, String>> completedImageData = unmarshallVnfcData(completedArtifact);\r
170             for (Map<String, String> data : completedImageData) {\r
171                 String url = config.getAaiBaseUrl() + config.getAaiVnfImageUrl() + "/vnf-image/" + data.get(ATTR_UUID);\r
172                 // Try to delete the image. If something goes wrong we can't really do anything here\r
173                 aaiClient.getAndDeleteResource(url, distributionId);\r
174             }\r
175         }\r
176     }\r
177 \r
178 }\r