2 * ============LICENSE_START=======================================================
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
23 package org.onap.policy.aai;
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;
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;
47 * This class handles communication towards and responses from A&AI for this module.
50 public final class AaiManager {
52 /** The Constant logger. */
53 private static final Logger logger = LoggerFactory.getLogger(AaiManager.class);
55 private static final String APPLICATION_JSON = "application/json";
57 private static final StandardCoder CODER = new StandardCoder();
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";
67 // The REST manager used for processing REST calls for this AAI manager
68 private final RestManager restManager;
71 * Creates the custom query payload from a tenant query response.
73 * @param getResponse response from the tenant query
74 * @return String Payload
76 private String createCustomQueryPayload(String getResponse) {
78 if (getResponse == null) {
81 var responseObj = new JSONObject(getResponse);
82 JSONArray resultsArray;
83 if (responseObj.has("result-data")) {
84 resultsArray = (JSONArray) responseObj.get("result-data");
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();
100 * This method is used to get the information for custom query.
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
109 private String getCustomQueryRequestPayload(String url, String username, String password, UUID requestId,
112 String urlGet = url + TENANT_URL;
114 var getResponse = getStringQuery(urlGet, username, password, requestId, vserver);
115 return createCustomQueryPayload(getResponse);
119 * Calls Aai and returns a custom query response for a vserver.
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
128 public AaiCqResponse getCustomQueryResponse(String url, String username, String password, UUID requestId,
131 final Map<String, String> headers = createHeaders(requestId);
133 logger.debug("RestManager.put before");
134 String requestJson = getCustomQueryRequestPayload(url, username, password, requestId, vserver);
135 NetLoggerUtil.log(EventType.OUT, CommInfrastructure.REST, url, requestJson);
139 Pair<Integer, String> httpDetails = this.restManager.put(url, username, password, headers, APPLICATION_JSON,
141 logger.debug("RestManager.put after");
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);
149 int httpResponseCode = httpDetails.getLeft();
151 NetLoggerUtil.log(EventType.IN, CommInfrastructure.REST, url, "Response code: " + httpResponseCode);
152 NetLoggerUtil.getNetworkLogger().debug(httpDetails.getRight());
155 logger.debug("{}", httpResponseCode);
156 logger.debug(httpDetails.getRight());
158 if (httpDetails.getRight() != null) {
159 return new AaiCqResponse(httpDetails.getRight());
165 * Returns the string response of a get query.
168 * @param username Aai Username
169 * @param password Aai Password
170 * @param requestId AaiRequestId
172 * @return String returns the string from the get query
174 private String getStringQuery(final String url, final String username, final String password, final UUID requestId,
177 Map<String, String> headers = createHeaders(requestId);
179 String urlGet = url + key;
181 var attemptsLeft = 3;
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);
192 int httpResponseCode = httpDetailsGet.getLeft();
194 NetLoggerUtil.log(EventType.IN, CommInfrastructure.REST, url, "Response code: " + httpResponseCode);
195 NetLoggerUtil.getNetworkLogger().debug(httpDetailsGet.getRight());
197 logger.debug(urlGet);
198 logger.debug("{}", httpResponseCode);
199 logger.debug(httpDetailsGet.getRight());
201 if (httpResponseCode == 200 && httpDetailsGet.getRight() != null) {
202 return httpDetailsGet.getRight();
206 } catch (InterruptedException e) {
207 Thread.currentThread().interrupt();
216 * Create the headers for the HTTP request.
218 * @param requestId the request ID to insert in the headers
219 * @return the HTTP headers
221 private Map<String, String> createHeaders(final UUID requestId) {
222 Map<String, String> headers = new HashMap<>();
224 headers.put("X-FromAppId", "POLICY");
225 headers.put("X-TransactionId", requestId.toString());
226 headers.put("Accept", APPLICATION_JSON);
232 * Perform a GET request for a particular PNF by PNF ID towards A&AI.
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
241 public Map<String, String> getPnf(String url, String username, String password, UUID requestId, String pnfName) {
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();
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();
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();