2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.onap.sdnc.apps.ms.gra.controllers;
23 import com.fasterxml.jackson.annotation.JsonInclude;
24 import com.fasterxml.jackson.core.JsonProcessingException;
25 import com.fasterxml.jackson.databind.JsonMappingException;
26 import com.fasterxml.jackson.databind.ObjectMapper;
27 import com.google.gson.JsonParser;
29 import org.onap.ccsdk.apps.services.RestException;
30 import org.onap.ccsdk.apps.services.SvcLogicFactory;
31 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
32 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
33 import org.onap.ccsdk.sli.core.sli.provider.base.SvcLogicServiceBase;
34 import org.onap.sdnc.apps.ms.gra.data.ConfigPreloadData;
35 import org.onap.sdnc.apps.ms.gra.data.ConfigPreloadDataRepository;
36 import org.onap.sdnc.apps.ms.gra.data.ConfigServices;
37 import org.onap.sdnc.apps.ms.gra.data.ConfigServicesRepository;
38 import org.onap.sdnc.apps.ms.gra.data.OperationalPreloadData;
39 import org.onap.sdnc.apps.ms.gra.data.OperationalPreloadDataRepository;
40 import org.onap.sdnc.apps.ms.gra.data.OperationalServices;
41 import org.onap.sdnc.apps.ms.gra.data.OperationalServicesRepository;
42 import org.onap.sdnc.apps.ms.gra.swagger.OperationsApi;
43 import org.onap.sdnc.apps.ms.gra.swagger.model.*;
44 import org.springframework.beans.factory.annotation.Autowired;
45 import org.springframework.boot.autoconfigure.domain.EntityScan;
46 import org.springframework.context.annotation.ComponentScan;
47 import org.springframework.context.annotation.Import;
48 import org.springframework.http.HttpStatus;
49 import org.springframework.http.ResponseEntity;
50 import org.springframework.stereotype.Controller;
52 import javax.servlet.http.HttpServletRequest;
53 import javax.validation.Valid;
55 import java.text.DateFormat;
56 import java.text.SimpleDateFormat;
58 import java.util.concurrent.atomic.AtomicBoolean;
61 @ComponentScan(basePackages = { "org.onap.sdnc.apps.ms.gra.*", "org.onap.ccsdk.apps.services" })
62 @EntityScan("org.onap.sdnc.apps.ms.gra.*")
63 @Import(value = SvcLogicFactory.class)
64 public class OperationsApiController implements OperationsApi {
66 private static final String CALLED_STR = "{} called.";
67 private static final String MODULE_NAME = "GENERIC-RESOURCE-API";
69 private final ObjectMapper objectMapper;
71 private final HttpServletRequest request;
74 protected SvcLogicServiceBase svc;
77 private ConfigPreloadDataRepository configPreloadDataRepository;
80 private OperationalPreloadDataRepository operationalPreloadDataRepository;
83 private ConfigServicesRepository configServicesRepository;
86 private OperationalServicesRepository operationalServicesRepository;
88 private static class Iso8601Util {
90 private static TimeZone timeZone = TimeZone.getTimeZone("UTC");
91 private static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
93 private Iso8601Util() {
97 dateFormat.setTimeZone(timeZone);
100 private static String now() {
101 return dateFormat.format(new Date());
105 @org.springframework.beans.factory.annotation.Autowired
106 public OperationsApiController(ObjectMapper objectMapper, HttpServletRequest request) {
107 objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
108 objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
109 this.objectMapper = objectMapper;
110 this.request = request;
114 public Optional<ObjectMapper> getObjectMapper() {
115 return Optional.ofNullable(objectMapper);
119 public Optional<HttpServletRequest> getRequest() {
120 return Optional.ofNullable(request);
124 public ResponseEntity<GenericResourceApiPreloadNetworkTopologyOperation> operationsGENERICRESOURCEAPIpreloadNetworkTopologyOperationPost(
125 @Valid GenericResourceApiPreloadnetworktopologyoperationInputBodyparam graInput) {
126 final String svcOperation = "preload-network-topology-operation";
127 GenericResourceApiPreloadNetworkTopologyOperation retval = new GenericResourceApiPreloadNetworkTopologyOperation();
128 GenericResourceApiPreloadTopologyResponseBody resp = new GenericResourceApiPreloadTopologyResponseBody();
130 log.info(CALLED_STR, svcOperation);
131 if (hasInvalidPreloadNetwork(graInput)) {
132 log.debug("exiting {} because of null or empty preload-network-topology-information", svcOperation);
134 resp.setResponseCode("403");
135 resp.setResponseMessage("invalid input, null or empty preload-network-topology-information");
136 resp.setAckFinalIndicator("Y");
138 retval.setOutput(resp);
140 return new ResponseEntity<>(retval, HttpStatus.FORBIDDEN);
143 String preloadId = graInput.getInput().getPreloadNetworkTopologyInformation()
144 .getNetworkTopologyIdentifierStructure().getNetworkId();
145 String preloadType = "network";
147 resp.setSvcRequestId(graInput.getInput().getSdncRequestHeader().getSvcRequestId());
149 SvcLogicContext ctxIn = new SvcLogicContext();
151 GenericResourceApiPreloaddataPreloadData preloadData = null;
153 // Add input to SvcLogicContext
155 ctxIn.mergeJson(svcOperation + "-input", objectMapper.writeValueAsString(graInput.getInput()));
156 } catch (JsonProcessingException e) {
157 log.error("exiting {} due to parse error on input preload data", svcOperation);
158 resp.setResponseCode("500");
159 resp.setResponseMessage("internal error");
160 resp.setAckFinalIndicator("Y");
161 retval.setOutput(resp);
162 return new ResponseEntity<>(retval, HttpStatus.INTERNAL_SERVER_ERROR);
165 // Add config tree data to SvcLogicContext
167 preloadData = getConfigPreloadData(preloadId, preloadType);
168 ctxIn.mergeJson("preload-data", objectMapper.writeValueAsString(preloadData));
169 } catch (JsonProcessingException e) {
170 log.error("exiting {} due to parse error on saved config preload data", svcOperation);
171 resp.setResponseCode("500");
172 resp.setResponseMessage("internal error");
173 resp.setAckFinalIndicator("Y");
174 retval.setOutput(resp);
175 return new ResponseEntity<>(retval, HttpStatus.INTERNAL_SERVER_ERROR);
178 // Add operational tree data to SvcLogicContext
180 preloadData = getOperationalPreloadData(preloadId, preloadType);
181 ctxIn.mergeJson("operational-data", objectMapper.writeValueAsString(preloadData));
182 } catch (JsonProcessingException e) {
183 log.error("exiting {} due to parse error on saved operational preload data", svcOperation);
184 resp.setResponseCode("500");
185 resp.setResponseMessage("internal error");
186 resp.setAckFinalIndicator("Y");
187 retval.setOutput(resp);
188 return new ResponseEntity<>(retval, HttpStatus.INTERNAL_SERVER_ERROR);
193 // Any of these can throw a nullpointer exception
194 // execute should only throw a SvcLogicException
195 SvcLogicContext ctxOut = svc.execute(MODULE_NAME, svcOperation, null, "sync", ctxIn);
196 Properties respProps = ctxOut.toProperties();
198 resp.setAckFinalIndicator(respProps.getProperty("ack-final-indicator", "Y"));
199 resp.setResponseCode(respProps.getProperty("error-code", "200"));
200 resp.setResponseMessage(respProps.getProperty("error-message", "SUCCESS"));
202 if ("200".equals(resp.getResponseCode())) {
203 // If DG returns success, update database
204 String ctxJson = ctxOut.toJsonString("preload-data");
205 log.info("DG preload-data is {}", ctxJson);
206 GenericResourceApiPreloaddataPreloadData preloadToLoad = objectMapper.readValue(ctxJson,
207 GenericResourceApiPreloaddataPreloadData.class);
208 saveConfigPreloadData(preloadId, preloadType, preloadToLoad);
209 saveOperationalPreloadData(preloadId, preloadType, preloadToLoad);
212 } catch (NullPointerException npe) {
213 log.error("Caught NPE", npe);
214 resp.setAckFinalIndicator("true");
215 resp.setResponseCode("500");
216 resp.setResponseMessage("Check that you populated module, rpc and or mode correctly.");
217 } catch (SvcLogicException e) {
218 log.error("Caught SvcLogicException", e);
219 resp.setAckFinalIndicator("true");
220 resp.setResponseCode("500");
221 resp.setResponseMessage(e.getMessage());
222 } catch (JsonMappingException e) {
223 log.error("Caught JsonMappingException", e);
224 resp.setAckFinalIndicator("true");
225 resp.setResponseCode("500");
226 resp.setResponseMessage(e.getMessage());
227 } catch (JsonProcessingException e) {
228 log.error("Caught JsonProcessingException", e);
229 resp.setAckFinalIndicator("true");
230 resp.setResponseCode("500");
231 resp.setResponseMessage(e.getMessage());
234 retval.setOutput(resp);
235 return (new ResponseEntity<>(retval, HttpStatus.valueOf(Integer.parseInt(resp.getResponseCode()))));
239 public ResponseEntity<GenericResourceApiPreloadVfModuleTopologyOperation> operationsGENERICRESOURCEAPIpreloadVfModuleTopologyOperationPost(
240 @Valid GenericResourceApiPreloadvfmoduletopologyoperationInputBodyparam graInput) {
241 final String svcOperation = "preload-vf-module-topology-operation";
242 GenericResourceApiPreloadVfModuleTopologyOperation retval = new GenericResourceApiPreloadVfModuleTopologyOperation();
243 GenericResourceApiPreloadTopologyResponseBody resp = new GenericResourceApiPreloadTopologyResponseBody();
245 log.info(CALLED_STR, svcOperation);
246 if (hasInvalidPreloadNetwork(graInput)) {
247 log.debug("exiting {} because of null or empty preload-network-topology-information", svcOperation);
249 resp.setResponseCode("403");
250 resp.setResponseMessage("invalid input, null or empty preload-network-topology-information");
251 resp.setAckFinalIndicator("Y");
253 retval.setOutput(resp);
255 return new ResponseEntity<>(retval, HttpStatus.FORBIDDEN);
258 String preloadId = graInput.getInput().getPreloadVfModuleTopologyInformation().getVfModuleTopology()
259 .getVfModuleTopologyIdentifier().getVfModuleName();
260 String preloadType = "vf-module";
262 resp.setSvcRequestId(graInput.getInput().getSdncRequestHeader().getSvcRequestId());
264 SvcLogicContext ctxIn = new SvcLogicContext();
266 GenericResourceApiPreloaddataPreloadData preloadData = null;
268 // Add input to SvcLogicContext
270 ctxIn.mergeJson(svcOperation + "-input", objectMapper.writeValueAsString(graInput.getInput()));
271 } catch (JsonProcessingException e) {
272 log.error("exiting {} due to parse error on input preload data", svcOperation);
273 resp.setResponseCode("500");
274 resp.setResponseMessage("internal error");
275 resp.setAckFinalIndicator("Y");
276 retval.setOutput(resp);
277 return new ResponseEntity<>(retval, HttpStatus.INTERNAL_SERVER_ERROR);
280 // Add config tree data to SvcLogicContext
282 preloadData = getConfigPreloadData(preloadId, preloadType);
283 ctxIn.mergeJson("preload-data", objectMapper.writeValueAsString(preloadData));
284 } catch (JsonProcessingException e) {
285 log.error("exiting {} due to parse error on saved config preload data", svcOperation);
286 resp.setResponseCode("500");
287 resp.setResponseMessage("internal error");
288 resp.setAckFinalIndicator("Y");
289 retval.setOutput(resp);
290 return new ResponseEntity<>(retval, HttpStatus.INTERNAL_SERVER_ERROR);
293 // Add operational tree data to SvcLogicContext
295 preloadData = getOperationalPreloadData(preloadId, preloadType);
296 ctxIn.mergeJson("operational-data", objectMapper.writeValueAsString(preloadData));
297 } catch (JsonProcessingException e) {
298 log.error("exiting {} due to parse error on saved operational preload data", svcOperation);
299 resp.setResponseCode("500");
300 resp.setResponseMessage("internal error");
301 resp.setAckFinalIndicator("Y");
302 retval.setOutput(resp);
303 return new ResponseEntity<>(retval, HttpStatus.INTERNAL_SERVER_ERROR);
308 // Any of these can throw a nullpointer exception
309 // execute should only throw a SvcLogicException
310 SvcLogicContext ctxOut = svc.execute(MODULE_NAME, svcOperation, null, "sync", ctxIn);
311 Properties respProps = ctxOut.toProperties();
313 resp.setAckFinalIndicator(respProps.getProperty("ack-final-indicator", "Y"));
314 resp.setResponseCode(respProps.getProperty("error-code", "200"));
315 resp.setResponseMessage(respProps.getProperty("error-message", "SUCCESS"));
317 if ("200".equals(resp.getResponseCode())) {
318 // If DG returns success, update database
319 String ctxJson = ctxOut.toJsonString("preload-data");
320 GenericResourceApiPreloaddataPreloadData preloadToLoad = objectMapper.readValue(ctxJson,
321 GenericResourceApiPreloaddataPreloadData.class);
322 saveConfigPreloadData(preloadId, preloadType, preloadToLoad);
323 saveOperationalPreloadData(preloadId, preloadType, preloadToLoad);
326 } catch (NullPointerException npe) {
327 resp.setAckFinalIndicator("true");
328 resp.setResponseCode("500");
329 resp.setResponseMessage("Check that you populated module, rpc and or mode correctly.");
330 } catch (SvcLogicException e) {
331 resp.setAckFinalIndicator("true");
332 resp.setResponseCode("500");
333 resp.setResponseMessage(e.getMessage());
334 } catch (JsonMappingException e) {
335 resp.setAckFinalIndicator("true");
336 resp.setResponseCode("500");
337 resp.setResponseMessage(e.getMessage());
338 } catch (JsonProcessingException e) {
339 resp.setAckFinalIndicator("true");
340 resp.setResponseCode("500");
341 resp.setResponseMessage(e.getMessage());
344 retval.setOutput(resp);
345 return (new ResponseEntity<>(retval, HttpStatus.valueOf(Integer.parseInt(resp.getResponseCode()))));
348 private boolean hasInvalidPreloadNetwork(
349 GenericResourceApiPreloadnetworktopologyoperationInputBodyparam preloadData) {
350 return ((preloadData == null) || (preloadData.getInput() == null)
351 || (preloadData.getInput().getPreloadNetworkTopologyInformation() == null));
354 private boolean hasInvalidPreloadNetwork(
355 GenericResourceApiPreloadvfmoduletopologyoperationInputBodyparam preloadData) {
356 return ((preloadData == null) || (preloadData.getInput() == null)
357 || (preloadData.getInput().getPreloadVfModuleTopologyInformation() == null));
360 private boolean hasInvalidServiceId(GenericResourceApiServiceOperationInformation input) {
362 return input == null || input.getServiceInformation() == null
363 || input.getServiceInformation().getServiceInstanceId() == null
364 || input.getServiceInformation().getServiceInstanceId().length() == 0;
367 private GenericResourceApiPreloaddataPreloadData getConfigPreloadData(String preloadId, String preloadType)
368 throws JsonProcessingException {
370 List<ConfigPreloadData> configPreloadData = configPreloadDataRepository.findByPreloadIdAndPreloadType(preloadId,
373 if (configPreloadData.isEmpty()) {
376 return (objectMapper.readValue(configPreloadData.get(0).getPreloadData(),
377 GenericResourceApiPreloaddataPreloadData.class));
381 private GenericResourceApiPreloaddataPreloadData getOperationalPreloadData(String preloadId, String preloadType)
382 throws JsonProcessingException {
384 List<OperationalPreloadData> configPreloadData = operationalPreloadDataRepository
385 .findByPreloadIdAndPreloadType(preloadId, preloadType);
387 if (configPreloadData.isEmpty()) {
390 return (objectMapper.readValue(configPreloadData.get(0).getPreloadData(),
391 GenericResourceApiPreloaddataPreloadData.class));
395 private void saveConfigPreloadData(String preloadId, String preloadType,
396 GenericResourceApiPreloaddataPreloadData preloadData) throws JsonProcessingException {
398 configPreloadDataRepository.deleteByPreloadIdAndPreloadType(preloadId, preloadType);
399 configPreloadDataRepository
400 .save(new ConfigPreloadData(preloadId, preloadType, objectMapper.writeValueAsString(preloadData)));
404 private void saveOperationalPreloadData(String preloadId, String preloadType,
405 GenericResourceApiPreloaddataPreloadData preloadData) throws JsonProcessingException {
407 operationalPreloadDataRepository.deleteByPreloadIdAndPreloadType(preloadId, preloadType);
408 operationalPreloadDataRepository
409 .save(new OperationalPreloadData(preloadId, preloadType, objectMapper.writeValueAsString(preloadData)));
413 private GenericResourceApiServicedataServiceData getConfigServiceData(String svcInstanceId) throws JsonProcessingException {
415 List<ConfigServices> configServices = configServicesRepository.findBySvcInstanceId(svcInstanceId);
417 if (configServices.isEmpty()) {
420 return (objectMapper.readValue(configServices.get(0).getSvcData(),
421 GenericResourceApiServicedataServiceData.class));
427 public ResponseEntity<GenericResourceApiNetworkTopologyOperation> operationsGENERICRESOURCEAPInetworkTopologyOperationPost(
428 @Valid GenericResourceApiNetworkOperationInformationBodyparam genericResourceApiNetworkOperationInformationBodyParam)
429 throws RestException {
430 // TODO Auto-generated method stub
431 return OperationsApi.super.operationsGENERICRESOURCEAPInetworkTopologyOperationPost(
432 genericResourceApiNetworkOperationInformationBodyParam);
436 public ResponseEntity<GenericResourceApiServiceTopologyOperation> operationsGENERICRESOURCEAPIserviceTopologyOperationPost(
437 @Valid GenericResourceApiServiceOperationInformationBodyparam input) throws RestException {
438 final String svcOperation = "service-topology-operation";
439 GenericResourceApiServiceTopologyOperation retval = new GenericResourceApiServiceTopologyOperation();
440 GenericResourceApiServicetopologyoperationOutput resp = new GenericResourceApiServicetopologyoperationOutput();
442 log.info(CALLED_STR, svcOperation);
444 // Verify input contains service instance id
445 if (hasInvalidServiceId(input.getInput())) {
446 log.debug("exiting {} because of null or empty service-instance-id", svcOperation);
448 resp.setResponseCode("404");
449 resp.setResponseMessage("null or empty service-instance-id");
450 resp.setAckFinalIndicator("Y");
452 retval.setOutput(resp);
454 return new ResponseEntity<>(retval, HttpStatus.OK);
457 String svcInstanceId = input.getInput().getServiceInformation().getServiceInstanceId();
459 SvcLogicContext ctxIn = new SvcLogicContext();
461 // Add input to SvcLogicContext
463 ctxIn.mergeJson(svcOperation + "-input", objectMapper.writeValueAsString(input.getInput()));
464 } catch (JsonProcessingException e) {
465 log.error("exiting {} due to parse error on input data", svcOperation);
466 resp.setResponseCode("500");
467 resp.setResponseMessage("internal error");
468 resp.setAckFinalIndicator("Y");
469 retval.setOutput(resp);
470 return new ResponseEntity<>(retval, HttpStatus.INTERNAL_SERVER_ERROR);
473 // Add config tree data to SvcLogicContext
474 List<ConfigServices> configServices = configServicesRepository.findBySvcInstanceId(svcInstanceId);
475 ConfigServices configService = null;
476 if (configServices != null && !configServices.isEmpty()) {
477 configService = configServices.get(0);
478 ctxIn.mergeJson("service-data", configService.getSvcData());
480 configService = new ConfigServices(svcInstanceId, null);
483 // Add operational tree data to SvcLogicContext
484 List<OperationalServices> operServices = operationalServicesRepository.findBySvcInstanceId(svcInstanceId);
485 OperationalServices operService = null;
486 boolean saveOperationalData = false;
488 if (operServices != null && !operServices.isEmpty()) {
489 operService = operServices.get(0);
490 ctxIn.mergeJson("operational-data", operService.getSvcData());
492 operService = new OperationalServices(svcInstanceId, null, null);
495 // Update service status info in config entry from input
496 configService.setServiceStatusAction(input.getInput().getRequestInformation().getRequestAction().toString());
497 configService.setServiceStatusRpcAction(input.getInput().getSdncRequestHeader().getSvcAction().toString());
498 configService.setServiceStatusRpcName(svcOperation);
503 // Any of these can throw a nullpointer exception
504 // execute should only throw a SvcLogicException
505 SvcLogicContext ctxOut = svc.execute(MODULE_NAME, svcOperation, null, "sync", ctxIn);
506 Properties respProps = ctxOut.toProperties();
508 resp.setAckFinalIndicator(respProps.getProperty("ack-final-indicator", "Y"));
509 resp.setResponseCode(respProps.getProperty("error-code", "200"));
510 resp.setResponseMessage(respProps.getProperty("error-message", "SUCCESS"));
511 configService.setServiceStatusRequestStatus(GenericResourceApiRequestStatusEnumeration.SYNCCOMPLETE.toString());
513 if ("200".equals(resp.getResponseCode())) {
514 // If DG returns success, update svcData in config and operational trees
515 // and remember to save operational data.
516 String ctxJson = ctxOut.toJsonString("service-data");
517 configService.setSvcData(ctxJson);
518 operService.setSvcData(ctxJson);
519 saveOperationalData = true;
522 } catch (NullPointerException npe) {
523 resp.setAckFinalIndicator("true");
524 resp.setResponseCode("500");
525 resp.setResponseMessage("Check that you populated module, rpc and or mode correctly.");
526 } catch (SvcLogicException e) {
527 resp.setAckFinalIndicator("true");
528 resp.setResponseCode("500");
529 resp.setResponseMessage(e.getMessage());
532 // Update status in config services entry
534 configService.setServiceStatusFinalIndicator(resp.getAckFinalIndicator());
535 configService.setServiceStatusResponseCode(resp.getResponseCode());
536 configService.setServiceStatusResponseMessage(resp.getResponseMessage());
537 configService.setServiceStatusResponseTimestamp(Iso8601Util.now());
539 // Update config tree
540 configServicesRepository.save(configService);
542 // If necessary, sync status to operation service entry and save
543 if (saveOperationalData) {
544 operService.setServiceStatus(configService.getServiceStatus());
545 operationalServicesRepository.save(operService);
547 retval.setOutput(resp);
548 return (new ResponseEntity<>(retval, HttpStatus.OK));