Fix trailing space in Info.yaml models
[policy/models.git] / models-interactions / model-impl / aai / src / main / java / org / onap / policy / aai / AaiManager.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * aai
4  * ================================================================================
5  * Copyright (C) 2017-2021 AT&T Intellectual Property. All rights reserved.
6  * Modifications Copyright (C) 2019-2020, 2024 Nordix Foundation.
7  * Modifications Copyright (C) 2019 Samsung Electronics Co., Ltd.
8  * ================================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.policy.aai;
24
25 import java.io.UnsupportedEncodingException;
26 import java.net.URLEncoder;
27 import java.nio.charset.StandardCharsets;
28 import java.util.Collections;
29 import java.util.HashMap;
30 import java.util.Map;
31 import java.util.UUID;
32 import java.util.stream.Collectors;
33 import lombok.AllArgsConstructor;
34 import org.apache.commons.lang3.tuple.Pair;
35 import org.json.JSONArray;
36 import org.json.JSONObject;
37 import org.onap.policy.common.message.bus.event.Topic.CommInfrastructure;
38 import org.onap.policy.common.message.bus.utils.NetLoggerUtil;
39 import org.onap.policy.common.message.bus.utils.NetLoggerUtil.EventType;
40 import org.onap.policy.common.utils.coder.CoderException;
41 import org.onap.policy.common.utils.coder.StandardCoder;
42 import org.onap.policy.rest.RestManager;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 /**
47  * This class handles communication towards and responses from A&AI for this module.
48  */
49 @AllArgsConstructor
50 public final class AaiManager {
51
52     /** The Constant logger. */
53     private static final Logger logger = LoggerFactory.getLogger(AaiManager.class);
54
55     private static final String APPLICATION_JSON = "application/json";
56
57     private static final StandardCoder CODER = new StandardCoder();
58
59     /** custom query and other AAI resource URLs. */
60     private static final String CQ_URL = "/aai/v21/query?format=resource";
61     private static final String TENANT_URL = "/aai/v21/search/nodes-query?"
62                     + "search-node-type=vserver&filter=vserver-name:EQUALS:";
63     private static final String PREFIX = "/aai/v21";
64     private static final String PNF_URL = PREFIX + "/network/pnfs/pnf/";
65     private static final String AAI_DEPTH_SUFFIX = "?depth=0";
66
67     // The REST manager used for processing REST calls for this AAI manager
68     private final RestManager restManager;
69
70     /**
71      * Creates the custom query payload from a tenant query response.
72      *
73      * @param getResponse response from the tenant query
74      * @return String Payload
75      */
76     private String createCustomQueryPayload(String getResponse) {
77
78         if (getResponse == null) {
79             return null;
80         } else {
81             var responseObj = new JSONObject(getResponse);
82             JSONArray resultsArray;
83             if (responseObj.has("result-data")) {
84                 resultsArray = (JSONArray) responseObj.get("result-data");
85             } else {
86                 return null;
87             }
88             var resourceLink = resultsArray.getJSONObject(0).getString("resource-link");
89             var start = resourceLink.replace(PREFIX, "");
90             var query = "query/closed-loop";
91             var payload = new JSONObject();
92             payload.put("start", start);
93             payload.put("query", query);
94             return payload.toString();
95
96         }
97     }
98
99     /**
100      * This method is used to get the information for custom query.
101      *
102      * @param url url of the get method
103      * @param username Aai username
104      * @param password Aai password
105      * @param requestId request ID
106      * @param vserver Id of the vserver
107      * @return String
108      */
109     private String getCustomQueryRequestPayload(String url, String username, String password, UUID requestId,
110                     String vserver) {
111
112         String urlGet = url + TENANT_URL;
113
114         var getResponse = getStringQuery(urlGet, username, password, requestId, vserver);
115         return createCustomQueryPayload(getResponse);
116     }
117
118     /**
119      * Calls Aai and returns a custom query response for a vserver.
120      *
121      * @param url Aai url
122      * @param username Aai Username
123      * @param password Aai Password
124      * @param requestId request ID
125      * @param vserver Vserver
126      * @return AaiCqResponse response from Aai for custom query
127      */
128     public AaiCqResponse getCustomQueryResponse(String url, String username, String password, UUID requestId,
129                     String vserver) {
130
131         final Map<String, String> headers = createHeaders(requestId);
132
133         logger.debug("RestManager.put before");
134         String requestJson = getCustomQueryRequestPayload(url, username, password, requestId, vserver);
135         NetLoggerUtil.log(EventType.OUT, CommInfrastructure.REST, url, requestJson);
136
137         url = url + CQ_URL;
138
139         Pair<Integer, String> httpDetails = this.restManager.put(url, username, password, headers, APPLICATION_JSON,
140                         requestJson);
141         logger.debug("RestManager.put after");
142
143         if (httpDetails == null) {
144             NetLoggerUtil.log(EventType.IN, CommInfrastructure.REST, url, "AAI POST Null Response");
145             logger.debug("AAI POST Null Response to {}", url);
146             return null;
147         }
148
149         int httpResponseCode = httpDetails.getLeft();
150
151         NetLoggerUtil.log(EventType.IN, CommInfrastructure.REST, url, "Response code: " + httpResponseCode);
152         NetLoggerUtil.getNetworkLogger().debug(httpDetails.getRight());
153
154         logger.debug(url);
155         logger.debug("{}", httpResponseCode);
156         logger.debug(httpDetails.getRight());
157
158         if (httpDetails.getRight() != null) {
159             return new AaiCqResponse(httpDetails.getRight());
160         }
161         return null;
162     }
163
164     /**
165      * Returns the string response of a get query.
166      *
167      * @param url Aai URL
168      * @param username Aai Username
169      * @param password Aai Password
170      * @param requestId AaiRequestId
171      * @param key Aai Key
172      * @return String returns the string from the get query
173      */
174     private String getStringQuery(final String url, final String username, final String password, final UUID requestId,
175                     final String key) {
176
177         Map<String, String> headers = createHeaders(requestId);
178
179         String urlGet = url + key;
180
181         var attemptsLeft = 3;
182
183         while (attemptsLeft-- > 0) {
184             NetLoggerUtil.getNetworkLogger().info("[OUT|{}|{}|]", CommInfrastructure.REST, urlGet);
185             Pair<Integer, String> httpDetailsGet = restManager.get(urlGet, username, password, headers);
186             if (httpDetailsGet == null) {
187                 NetLoggerUtil.log(EventType.IN, CommInfrastructure.REST, url, "AAI POST Null Response");
188                 logger.debug("AAI GET Null Response to {}", urlGet);
189                 return null;
190             }
191
192             int httpResponseCode = httpDetailsGet.getLeft();
193
194             NetLoggerUtil.log(EventType.IN, CommInfrastructure.REST, url, "Response code: " + httpResponseCode);
195             NetLoggerUtil.getNetworkLogger().debug(httpDetailsGet.getRight());
196
197             logger.debug(urlGet);
198             logger.debug("{}", httpResponseCode);
199             logger.debug(httpDetailsGet.getRight());
200
201             if (httpResponseCode == 200 && httpDetailsGet.getRight() != null) {
202                 return httpDetailsGet.getRight();
203             }
204             try {
205                 Thread.sleep(1000);
206             } catch (InterruptedException e) {
207                 Thread.currentThread().interrupt();
208             }
209
210         }
211
212         return null;
213     }
214
215     /**
216      * Create the headers for the HTTP request.
217      *
218      * @param requestId the request ID to insert in the headers
219      * @return the HTTP headers
220      */
221     private Map<String, String> createHeaders(final UUID requestId) {
222         Map<String, String> headers = new HashMap<>();
223
224         headers.put("X-FromAppId", "POLICY");
225         headers.put("X-TransactionId", requestId.toString());
226         headers.put("Accept", APPLICATION_JSON);
227
228         return headers;
229     }
230
231     /**
232      * Perform a GET request for a particular PNF by PNF ID towards A&AI.
233      *
234      * @param url the A&AI URL
235      * @param username the user name for authentication
236      * @param password the password for authentication
237      * @param requestId the UUID of the request
238      * @param pnfName the AAI unique identifier for PNF object
239      * @return HashMap of PNF properties
240      */
241     public Map<String, String> getPnf(String url, String username, String password, UUID requestId, String pnfName) {
242         String urlGet;
243         try {
244             urlGet = url + PNF_URL;
245             pnfName = URLEncoder.encode(pnfName, StandardCharsets.UTF_8.toString()) + AAI_DEPTH_SUFFIX;
246         } catch (UnsupportedEncodingException e) {
247             logger.error("Failed to encode the pnfName: {} using UTF-8", pnfName, e);
248             return Collections.emptyMap();
249         }
250         var responseGet = getStringQuery(urlGet, username, password, requestId, pnfName);
251         if (responseGet == null) {
252             logger.error("Null response from AAI for the url: {}.", urlGet);
253             return Collections.emptyMap();
254         }
255         try {
256             @SuppressWarnings("unchecked")
257             Map<String, String> pnfParams = CODER.decode(responseGet, HashMap.class);
258             // Map to AAI node.attribute notation
259             return pnfParams.entrySet().stream()
260                             .collect(Collectors.toMap(e -> "pnf." + e.getKey(), Map.Entry::getValue));
261         } catch (CoderException e) {
262             logger.error("Failed to fetch PNF from AAI", e);
263             return Collections.emptyMap();
264         }
265     }
266 }