8693f493de9cdacec548b06a0d671aba3077d124
[ccsdk/oran.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2020 Nordix Foundation.
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
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
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  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.ccsdk.features.a1.adapter;
22
23 import static org.apache.http.HttpStatus.SC_INTERNAL_SERVER_ERROR;
24 import static org.apache.http.HttpStatus.SC_SERVICE_UNAVAILABLE;
25
26 import com.google.common.util.concurrent.Futures;
27 import com.google.common.util.concurrent.ListenableFuture;
28 import java.lang.reflect.Method;
29 import java.util.Properties;
30 import java.util.concurrent.ExecutorService;
31 import java.util.concurrent.Executors;
32 import org.onap.ccsdk.sli.core.sli.provider.MdsalHelper;
33 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
34 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
35 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
36 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.A1ADAPTERAPIService;
37 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.DeleteA1PolicyInput;
38 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.DeleteA1PolicyInputBuilder;
39 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.DeleteA1PolicyOutput;
40 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.DeleteA1PolicyOutputBuilder;
41 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.GetA1PolicyInput;
42 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.GetA1PolicyInputBuilder;
43 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.GetA1PolicyOutput;
44 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.GetA1PolicyOutputBuilder;
45 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.GetA1PolicyStatusInput;
46 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.GetA1PolicyStatusInputBuilder;
47 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.GetA1PolicyStatusOutput;
48 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.GetA1PolicyStatusOutputBuilder;
49 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.GetA1PolicyTypeInput;
50 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.GetA1PolicyTypeInputBuilder;
51 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.GetA1PolicyTypeOutput;
52 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.GetA1PolicyTypeOutputBuilder;
53 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.PutA1PolicyInput;
54 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.PutA1PolicyInputBuilder;
55 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.PutA1PolicyOutput;
56 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.PutA1PolicyOutputBuilder;
57 import org.opendaylight.yangtools.concepts.Builder;
58 import org.opendaylight.yangtools.yang.common.RpcResult;
59 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
60 import org.slf4j.Logger;
61 import org.slf4j.LoggerFactory;
62
63 /**
64  * This class implements the generated interface from the YANG model and implements the request model for the A1
65  * interface. This class identifies the Near-RT RIC throughout the IP passed over the payload and calls the
66  * corresponding Near-RT RIC over Rest API.
67  */
68 @SuppressWarnings("squid:S1874") // "@Deprecated" code should not be used
69 public class A1AdapterProvider implements AutoCloseable, A1ADAPTERAPIService {
70
71     private static final String START_OPERATION_MESSAGE = "Start of {}";
72     private static final String END_OPERATION_MESSAGE = "End of {}";
73
74     private static final String A1_ADAPTER_API = "A1-ADAPTER-API";
75     private static final String RESPONSE_BODY = "responseBody";
76     private static final String RESPONSE_CODE = "response-code";
77     private static final String SYNC = "sync";
78
79     private static final Logger log = LoggerFactory.getLogger(A1AdapterProvider.class);
80
81     private static final String APPLICATION_NAME = "a1Adapter-api";
82
83     private final ExecutorService executor;
84     protected NotificationPublishService notificationService;
85     protected RpcProviderRegistry rpcRegistry;
86     protected BindingAwareBroker.RpcRegistration<A1ADAPTERAPIService> rpcRegistration;
87     private final A1AdapterClient a1AdapterClient;
88
89     public A1AdapterProvider(final NotificationPublishService notificationPublishService,
90         final RpcProviderRegistry rpcProviderRegistry, final A1AdapterClient a1AdapterClient) {
91
92         log.info("Creating provider for {}", APPLICATION_NAME);
93         executor = Executors.newFixedThreadPool(1);
94         this.notificationService = notificationPublishService;
95         this.rpcRegistry = rpcProviderRegistry;
96         this.a1AdapterClient = a1AdapterClient;
97         initialize();
98     }
99
100     public void initialize() {
101         log.info("Initializing provider for {}", APPLICATION_NAME);
102         rpcRegistration = rpcRegistry.addRpcImplementation(A1ADAPTERAPIService.class, this);
103         log.info("Initialization complete for {}", APPLICATION_NAME);
104     }
105
106     @Override
107     public void close() throws Exception {
108         log.info("Closing provider for {}", APPLICATION_NAME);
109         executor.shutdown();
110         rpcRegistration.close();
111         log.info("Successfully closed provider for {}", APPLICATION_NAME);
112     }
113
114     @Override
115     public ListenableFuture<RpcResult<DeleteA1PolicyOutput>> deleteA1Policy(DeleteA1PolicyInput deletePolicyInput) {
116         final String svcOperation = "deleteA1Policy";
117         log.info(START_OPERATION_MESSAGE, svcOperation);
118         DeleteA1PolicyOutputBuilder deletePolicyResponse = new DeleteA1PolicyOutputBuilder();
119         setUpAndExecuteOperation(svcOperation, new DeleteA1PolicyInputBuilder(deletePolicyInput), deletePolicyResponse);
120
121         RpcResult<DeleteA1PolicyOutput> deletePolicyResult =
122             RpcResultBuilder.<DeleteA1PolicyOutput>status(true).withResult(deletePolicyResponse.build()).build();
123         log.info(END_OPERATION_MESSAGE, svcOperation);
124         return Futures.immediateFuture(deletePolicyResult);
125     }
126
127     @Override
128     public ListenableFuture<RpcResult<GetA1PolicyOutput>> getA1Policy(GetA1PolicyInput getPolicyInput) {
129         final String svcOperation = "getA1Policy";
130         log.info(START_OPERATION_MESSAGE, svcOperation);
131         GetA1PolicyOutputBuilder getPolicyResponse = new GetA1PolicyOutputBuilder();
132         setUpAndExecuteOperation(svcOperation, new GetA1PolicyInputBuilder(getPolicyInput), getPolicyResponse);
133
134         RpcResult<GetA1PolicyOutput> getPolicyResult =
135             RpcResultBuilder.<GetA1PolicyOutput>status(true).withResult(getPolicyResponse.build()).build();
136         log.info(END_OPERATION_MESSAGE, svcOperation);
137         return Futures.immediateFuture(getPolicyResult);
138     }
139
140     @Override
141     public ListenableFuture<RpcResult<GetA1PolicyStatusOutput>> getA1PolicyStatus(
142         GetA1PolicyStatusInput getPolicyStatusInput) {
143         final String svcOperation = "getA1PolicyStatus";
144         log.info(START_OPERATION_MESSAGE, svcOperation);
145         GetA1PolicyStatusOutputBuilder getPolicyStatusResponse = new GetA1PolicyStatusOutputBuilder();
146         setUpAndExecuteOperation(svcOperation, new GetA1PolicyStatusInputBuilder(getPolicyStatusInput),
147             getPolicyStatusResponse);
148
149         RpcResult<GetA1PolicyStatusOutput> getPolicyStatusResult =
150             RpcResultBuilder.<GetA1PolicyStatusOutput>status(true).withResult(getPolicyStatusResponse.build()).build();
151         log.info(END_OPERATION_MESSAGE, svcOperation);
152         return Futures.immediateFuture(getPolicyStatusResult);
153     }
154
155     @Override
156     public ListenableFuture<RpcResult<GetA1PolicyTypeOutput>> getA1PolicyType(GetA1PolicyTypeInput getPolicyTypeInput) {
157         final String svcOperation = "getA1PolicyType";
158         log.info(START_OPERATION_MESSAGE, svcOperation);
159         GetA1PolicyTypeOutputBuilder getPolicyTypeResponse = new GetA1PolicyTypeOutputBuilder();
160         setUpAndExecuteOperation(svcOperation, new GetA1PolicyTypeInputBuilder(getPolicyTypeInput),
161             getPolicyTypeResponse);
162
163         RpcResult<GetA1PolicyTypeOutput> getPolicyTypeResult =
164             RpcResultBuilder.<GetA1PolicyTypeOutput>status(true).withResult(getPolicyTypeResponse.build()).build();
165         log.info(END_OPERATION_MESSAGE, svcOperation);
166         return Futures.immediateFuture(getPolicyTypeResult);
167     }
168
169     @Override
170     public ListenableFuture<RpcResult<PutA1PolicyOutput>> putA1Policy(PutA1PolicyInput putPolicyInput) {
171         final String svcOperation = "putA1Policy";
172         log.info(START_OPERATION_MESSAGE, svcOperation);
173         PutA1PolicyOutputBuilder putPolicyResponse = new PutA1PolicyOutputBuilder();
174         setUpAndExecuteOperation(svcOperation, new PutA1PolicyInputBuilder(putPolicyInput), putPolicyResponse);
175
176         RpcResult<PutA1PolicyOutput> putPolicyResult =
177             RpcResultBuilder.<PutA1PolicyOutput>status(true).withResult(putPolicyResponse.build()).build();
178         log.info(END_OPERATION_MESSAGE, svcOperation);
179         return Futures.immediateFuture(putPolicyResult);
180     }
181
182     private <T> boolean hasGraph(final String svcOperation, Builder<T> response) {
183         try {
184             return a1AdapterClient.hasGraph(A1_ADAPTER_API, svcOperation, null, SYNC);
185         } catch (Exception e) {
186             log.error("Caught exception looking for service logic, {}", e.getMessage());
187             setHttpResponse(response, SC_INTERNAL_SERVER_ERROR);
188         }
189         return false;
190     }
191
192     private <U, T> void setUpAndExecuteOperation(final String svcOperation, Builder<U> inputBuilder,
193         Builder<T> responseBuilder) {
194         log.info("Adding INPUT data for {} input: {}", svcOperation, inputBuilder);
195         // add input to parms
196         Properties parms = new Properties();
197         MdsalHelper.toProperties(parms, inputBuilder.build());
198         logSliParameters(parms);
199         // Call SLI sync method
200         if (hasGraph(svcOperation, responseBuilder)) {
201             log.info("A1AdapterClient has a Directed Graph for '{}'", svcOperation);
202             executeOperation(svcOperation, parms, responseBuilder);
203         } else {
204             log.error("No service logic active for A1Adapter: '{}'", svcOperation);
205             setHttpResponse(responseBuilder, Integer.valueOf(SC_SERVICE_UNAVAILABLE));
206         }
207     }
208
209     private <T> void executeOperation(final String svcOperation, Properties parms, Builder<T> response) {
210         try {
211             Properties responseParms =
212                 a1AdapterClient.execute(A1_ADAPTER_API, svcOperation, null, SYNC, response, parms);
213             logResponse(responseParms);
214             setBody(response, responseParms.getProperty(RESPONSE_BODY));
215             setHttpResponse(response, Integer.valueOf(responseParms.getProperty(RESPONSE_CODE)));
216         } catch (Exception e) {
217             log.error("Caught exception executing service logic for {}, {}", svcOperation, e.getMessage());
218             setHttpResponse(response, Integer.valueOf(SC_INTERNAL_SERVER_ERROR));
219         }
220     }
221
222     private <T> void setBody(Builder<T> responseBuilder, String body) {
223         try {
224             Method method = responseBuilder.getClass().getMethod("setBody", String.class);
225             method.invoke(responseBuilder, body);
226         } catch (Exception reflectionException) {
227             throw new MissingResponseMethodRuntimeException(reflectionException);
228         }
229     }
230
231     private <T> void setHttpResponse(Builder<T> responseBuilder, Integer response) {
232         try {
233             Method method = responseBuilder.getClass().getMethod("setHttpStatus", Integer.class);
234             method.invoke(responseBuilder, response);
235         } catch (Exception reflectionException) {
236             throw new MissingResponseMethodRuntimeException(reflectionException);
237         }
238     }
239
240     private void logSliParameters(Properties parms) {
241         log.info("Printing SLI parameters to be passed");
242         // iterate properties file to get key-value pairs
243         for (String key : parms.stringPropertyNames()) {
244             String value = parms.getProperty(key);
245             log.info("The SLI parameter in {} is: {}", key, value);
246         }
247     }
248
249     private void logResponse(Properties responseParms) {
250         log.info("responseBody::{}", responseParms.getProperty(RESPONSE_BODY));
251         log.info("responseCode::{}", responseParms.getProperty(RESPONSE_CODE));
252         log.info("responseMessage::{}", responseParms.getProperty("response-message"));
253     }
254
255     public class MissingResponseMethodRuntimeException extends RuntimeException {
256         private static final long serialVersionUID = -6803869291161765099L;
257
258         MissingResponseMethodRuntimeException(Exception e) {
259             super(e);
260         }
261     }
262 }