2 * ================================================================================
3 * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
4 * ================================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 * ============LICENSE_END=========================================================
20 package org.onap.dcae.analytics.tca.web.aai;
22 import static org.onap.dcae.analytics.tca.model.util.json.TcaModelJsonConversion.TCA_OBJECT_MAPPER;
24 import java.io.IOException;
26 import java.util.Collections;
27 import java.util.Iterator;
31 import org.onap.dcae.analytics.model.AnalyticsHttpConstants;
32 import org.onap.dcae.analytics.model.TcaModelConstants;
33 import org.onap.dcae.analytics.tca.core.service.TcaAaiEnrichmentService;
34 import org.onap.dcae.analytics.tca.core.service.TcaExecutionContext;
35 import org.onap.dcae.analytics.tca.core.util.LogSpec;
36 import org.onap.dcae.analytics.tca.model.facade.Aai;
37 import org.onap.dcae.analytics.tca.model.facade.TcaAlert;
38 import org.onap.dcae.analytics.tca.web.TcaAppProperties;
39 import org.onap.dcae.utils.eelf.logger.api.log.EELFLogFactory;
40 import org.onap.dcae.utils.eelf.logger.api.log.EELFLogger;
41 import org.onap.dcae.utils.eelf.logger.api.spec.DebugLogSpec;
42 import org.onap.dcae.utils.eelf.logger.api.spec.ErrorLogSpec;
43 import org.springframework.http.HttpEntity;
44 import org.springframework.http.HttpHeaders;
45 import org.springframework.http.HttpMethod;
46 import org.springframework.http.ResponseEntity;
47 import org.springframework.util.StringUtils;
48 import org.springframework.web.client.RestTemplate;
49 import org.springframework.web.util.UriComponentsBuilder;
51 import com.fasterxml.jackson.databind.JsonNode;
54 * @author Rajiv Singla
56 public class TcaAaiEnrichmentServiceImpl implements TcaAaiEnrichmentService {
58 private static final EELFLogger logger = EELFLogFactory.getLogger(TcaAaiEnrichmentServiceImpl.class);
60 private final TcaAppProperties tcaAppProperties;
61 private final RestTemplate aaiRestTemplate;
63 public TcaAaiEnrichmentServiceImpl(final TcaAppProperties tcaAppProperties,
64 final RestTemplate aaiRestTemplate) {
65 this.tcaAppProperties = tcaAppProperties;
66 this.aaiRestTemplate = aaiRestTemplate;
71 public TcaAlert doAaiEnrichment(final TcaExecutionContext tcaExecutionContext) {
73 final TcaAlert tcaAlert = tcaExecutionContext.getTcaResultContext().getTcaAlert();
76 if (isVNFAlert(tcaAlert)) {
78 doAaiVnfEnrichment(tcaExecutionContext, aaiRestTemplate, tcaAppProperties);
81 doAaiVmEnrichment(tcaExecutionContext, aaiRestTemplate, tcaAppProperties);
87 private static void doAaiVmEnrichment(final TcaExecutionContext tcaExecutionContext,
88 final RestTemplate aaiRestTemplate,
89 final TcaAppProperties tcaAppProperties) {
91 final TcaAlert tcaAlert = tcaExecutionContext.getTcaResultContext().getTcaAlert();
92 final String requestId = tcaExecutionContext.getRequestId();
93 final String transactionId = tcaExecutionContext.getTransactionId();
94 final String vServerName = tcaAlert.getAai().getGenericServerName();
96 // create new node query uri
97 final TcaAppProperties.Aai aai = tcaAppProperties.getTca().getAai();
98 final URI nodeQueryUri = UriComponentsBuilder.fromHttpUrl(aai.getUrl())
99 .path(aai.getNodeQueryPath())
100 .queryParam("search-node-type", "vserver")
101 .queryParam("filter", "vserver-name:EQUALS:" + vServerName)
102 .build(Collections.emptyMap());
105 final String resourceLink =
106 getVMResourceLink(requestId, getAAIRestAPIResponse(aaiRestTemplate, nodeQueryUri, requestId, transactionId));
107 if (resourceLink == null) {
111 // create virtual server enrichment uri
112 final URI vServerEnrichmentUri = UriComponentsBuilder.fromHttpUrl(aai.getUrl())
114 .build(Collections.emptyMap());
116 // fetch virtual server enrichment details
117 final String vServerEnrichmentDetails =
118 getAAIRestAPIResponse(aaiRestTemplate, vServerEnrichmentUri, requestId, transactionId);
121 enrichAAI(requestId, vServerEnrichmentDetails, tcaAlert, TcaModelConstants.AAI_VSERVER_KEY_PREFIX);
124 private static void doAaiVnfEnrichment(final TcaExecutionContext tcaExecutionContext,
125 final RestTemplate aaiRestTemplate,
126 final TcaAppProperties tcaAppProperties) {
128 final TcaAlert tcaAlert = tcaExecutionContext.getTcaResultContext().getTcaAlert();
129 final String requestId = tcaExecutionContext.getRequestId();
130 final String transactionId = tcaExecutionContext.getTransactionId();
131 final String genericVnfName = tcaAlert.getAai().getGenericVNFName();
133 // create new generic vnf uri
134 final TcaAppProperties.Aai aai = tcaAppProperties.getTca().getAai();
135 final URI genericVnfUri = UriComponentsBuilder.fromHttpUrl(aai.getUrl())
136 .path(aai.getGenericVnfPath())
137 .queryParam("vnf-name", genericVnfName)
138 .build(Collections.emptyMap());
141 final String aaiResponse = getAAIRestAPIResponse(aaiRestTemplate, genericVnfUri, requestId, transactionId);
144 enrichAAI(requestId, aaiResponse, tcaAlert, TcaModelConstants.AAI_VNF_KEY_PREFIX);
149 * Fetch response from A&AI Rest API as json string for given aai uri. Returns null if unable to fetch response
152 * @param aaiRestTemplate aai rest template
153 * @param aaiUri aai uri
155 * @return A&AI API response as json string
157 private static String getAAIRestAPIResponse(final RestTemplate aaiRestTemplate, final URI aaiUri,
158 final String requestId, final String transactionId) {
160 ResponseEntity<String> aaiResponseEntity = null;
162 final HttpHeaders headers = new HttpHeaders();
163 headers.add(AnalyticsHttpConstants.REQUEST_ID_HEADER_KEY, requestId);
164 headers.add(AnalyticsHttpConstants.REQUEST_TRANSACTION_ID_HEADER_KEY, transactionId);
165 final HttpEntity<String> httpEntity = new HttpEntity<>(headers);
166 aaiResponseEntity = aaiRestTemplate.exchange(aaiUri, HttpMethod.GET, httpEntity, String.class);
167 } catch (Exception e) {
168 final ErrorLogSpec errorLogSpec = LogSpec.createErrorLogSpec(requestId);
169 logger.errorLog().error("Request id: " + requestId + ". Unable to get A&AI enrichment details",
170 errorLogSpec, e.toString());
173 if (aaiResponseEntity != null && aaiResponseEntity.getStatusCode().is2xxSuccessful()) {
174 return aaiResponseEntity.getBody();
182 * Populates A&AI details retrieved from A&AI Enrichment API into Alerts A&AI Object
184 * @param aaiEnrichmentDetails A&AI Enrichment API fetched JSON String
185 * @param tcaAlert tca alert
186 * @param keyPrefix Key prefix that needs to be added to each fetched A&AI Enrichment record
188 * @return true if A&AI enrichment completed successfully
190 private static boolean enrichAAI(final String requestId, final String aaiEnrichmentDetails, final TcaAlert tcaAlert,
191 final String keyPrefix) {
193 final Aai preEnrichmentAAI = tcaAlert.getAai();
194 final ErrorLogSpec errorLogSpec = LogSpec.createErrorLogSpec(requestId);
195 final DebugLogSpec debugLogSpec = LogSpec.createDebugLogSpec(requestId);
197 if (aaiEnrichmentDetails == null) {
198 logger.errorLog().error("Request id: {}. No A&AI Enrichment possible. A&AI Enrichment details are absent.",
199 errorLogSpec, tcaAlert.getRequestId());
203 final Aai enrichedAAI = getNewEnrichedAAI(requestId, aaiEnrichmentDetails);
205 if (enrichedAAI != null) {
206 final Set<Map.Entry<String, Object>> enrichedAAIEntrySet =
207 enrichedAAI.getDynamicProperties().entrySet();
208 final Map<String, Object> preEnrichmentAAIDynamicProperties = preEnrichmentAAI.getDynamicProperties();
210 // populate Alert A&AI Enrichment details and add prefix to key
211 for (Map.Entry<String, Object> enrichedAAIEntry : enrichedAAIEntrySet) {
212 preEnrichmentAAIDynamicProperties.put(
213 keyPrefix + enrichedAAIEntry.getKey(), enrichedAAIEntry.getValue());
216 logger.debugLog().debug("Request id: {}. A&AI Enrichment was completed successfully.",
217 debugLogSpec, tcaAlert.getRequestId());
220 logger.errorLog().error("Request id: {}. No A&AI Enrichment possible. Skipped - Invalid A&AI Response.",
221 errorLogSpec, tcaAlert.getRequestId());
228 * Creates a new A&AI object with only top level A&AI Enrichment details
230 * @param aaiEnrichmentDetails A&AI Enrichment details
232 * @return new A&AI with only top level A&AI Enrichment details
234 private static Aai getNewEnrichedAAI(final String requestId, final String aaiEnrichmentDetails) {
236 final JsonNode rootNode = TCA_OBJECT_MAPPER.readTree(aaiEnrichmentDetails);
237 final Iterator<Map.Entry<String, JsonNode>> fieldsIterator = rootNode.fields();
238 while (fieldsIterator.hasNext()) {
239 final Map.Entry<String, JsonNode> fieldEntry = fieldsIterator.next();
240 final JsonNode jsonNode = fieldEntry.getValue();
241 // remove all arrays, objects from A&AI Enrichment Json
242 if (jsonNode.isPojo() || jsonNode.isObject() || jsonNode.isArray()) {
243 fieldsIterator.remove();
246 return TCA_OBJECT_MAPPER.treeToValue(rootNode, Aai.class);
247 } catch (IOException e) {
248 final ErrorLogSpec errorLogSpec = LogSpec.createErrorLogSpec(requestId);
249 logger.errorLog().error(
250 "Failed to Parse AAI Enrichment Details from JSON: {}, Exception: {}.",
251 errorLogSpec, aaiEnrichmentDetails, e.toString());
257 * Fetches VM Object Resource Link from A&AI Resource Link Json
259 * @param vmAAIResourceLinkDetails VM Object Resource Link from A&AI Resource Link Json
261 * @return object resource link String
263 private static String getVMResourceLink(final String requestId, final String vmAAIResourceLinkDetails) {
264 if (StringUtils.hasText(vmAAIResourceLinkDetails)) {
266 final JsonNode jsonNode = TCA_OBJECT_MAPPER.readTree(vmAAIResourceLinkDetails);
267 final JsonNode resourceLinkJsonNode = jsonNode.findPath("resource-link");
268 if (!resourceLinkJsonNode.isMissingNode()) {
269 return resourceLinkJsonNode.asText();
271 } catch (IOException e) {
272 final ErrorLogSpec errorLogSpec = LogSpec.createErrorLogSpec(requestId);
273 logger.errorLog().error("Unable to determine VM Object link inside AAI Resource Link Response JSON: {}",
274 errorLogSpec, vmAAIResourceLinkDetails, e.toString());
281 private static boolean isVNFAlert(final TcaAlert tcaAlert) {
282 return tcaAlert.getTargetType().equals(TcaModelConstants.TCA_ALERT_VNF_TARGET_TYPE);