From 6ad41e3ccd398a2721f41ad61c80b7bb03f7d127 Mon Sep 17 00:00:00 2001 From: Ittay Stern Date: Mon, 31 Dec 2018 17:21:27 +0200 Subject: Merge from ECOMP's repository Main Features -------------- - Async-Instantiation jobs mechanism major update; still WIP (package `org.onap.vid.job`) - New features in View/Edit: Activate fabric configuration; show related networks; soft delete - Support AAI service-tree traversal (`AAIServiceTree`) - In-memory cache for SDC models and certain A&AI queries (`CacheProviderWithLoadingCache`) - Upgrade TOSCA Parser and add parsing options; fix malformed TOSCA models - Resolve Cloud-Owner values for MSO - Pass X-ONAP headers to MSO Infrastructure -------------- - Remove codehaus' jackson mapper; use soley fasterxml 2.9.7 - Surefire invokes both TestNG and JUnit tests - Support Kotlin source files - AaiController2 which handles errors in a "Spring manner" - Inline generated-sources and remove jsonschema2pojo Quality -------- - Cumulative bug fixes (A&AI API, UI timeouts, and many more) - Many Sonar issues cleaned-up - Some unused classes removed - Minor changes in vid-automation project, allowing some API verification to run Hard Merges ------------ - HTTP Clients (MSO, A&AI, WebConfig, OutgoingRequestHeadersTest) - Moved `package org.onap.vid.controllers` to `controller`, without plural -- just to keep semantic sync with ECOMP. Reference commit in ECOMP: 3d1141625 Issue-ID: VID-378 Change-Id: I9c8d1e74caa41815891d441fc0760bb5f29c5788 Signed-off-by: Ittay Stern --- .../org/onap/vid/controller/AaiController.java | 731 +++++++++++++++++++++ .../org/onap/vid/controller/AaiController2.java | 98 +++ .../AaiServiceInstanceStandardQueryController.java | 173 +++++ .../vid/controller/AsyncControllerForTests.java | 48 ++ .../controller/AsyncInstantiationController.java | 104 +++ .../vid/controller/ChangeManagementController.java | 213 ++++++ .../org/onap/vid/controller/ControllersUtils.java | 45 ++ .../vid/controller/FeatureTogglingController.java | 29 + .../onap/vid/controller/HealthCheckController.java | 135 ++++ .../java/org/onap/vid/controller/HealthStatus.java | 31 + .../org/onap/vid/controller/LoggerController.java | 115 ++++ .../onap/vid/controller/MaintenanceController.java | 152 +++++ .../java/org/onap/vid/controller/MsoConfig.java | 66 ++ .../org/onap/vid/controller/MsoController.java | 705 ++++++++++++++++++++ .../OperationalEnvironmentController.java | 362 ++++++++++ .../org/onap/vid/controller/ProbeController.java | 42 ++ .../onap/vid/controller/PropertyController.java | 126 ++++ .../vid/controller/RoleGeneratorController.java | 26 + .../org/onap/vid/controller/VersionController.java | 63 ++ .../org/onap/vid/controller/VidController.java | 114 ++++ .../controller/VidRestrictedBaseController.java | 42 ++ .../org/onap/vid/controller/ViewLogController.java | 65 ++ .../java/org/onap/vid/controller/WebConfig.java | 193 ++++++ .../controller/filter/ClientCredentialsFilter.java | 10 +- .../filter/PromiseEcompRequestIdFilter.java | 17 +- .../vid/controller/test/TestAaiController.java | 2 +- .../vid/controller/test/TestAsdcController.java | 2 +- .../vid/controller/test/TestMsoController.java | 2 +- 28 files changed, 3699 insertions(+), 12 deletions(-) create mode 100644 vid-app-common/src/main/java/org/onap/vid/controller/AaiController.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/controller/AaiController2.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/controller/AaiServiceInstanceStandardQueryController.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/controller/AsyncControllerForTests.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/controller/AsyncInstantiationController.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/controller/ChangeManagementController.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/controller/ControllersUtils.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/controller/FeatureTogglingController.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/controller/HealthCheckController.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/controller/HealthStatus.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/controller/LoggerController.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/controller/MaintenanceController.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/controller/MsoConfig.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/controller/MsoController.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/controller/OperationalEnvironmentController.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/controller/ProbeController.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/controller/PropertyController.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/controller/RoleGeneratorController.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/controller/VersionController.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/controller/VidController.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/controller/VidRestrictedBaseController.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/controller/ViewLogController.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/controller/WebConfig.java (limited to 'vid-app-common/src/main/java/org/onap/vid/controller') diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/AaiController.java b/vid-app-common/src/main/java/org/onap/vid/controller/AaiController.java new file mode 100644 index 000000000..c099db807 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/controller/AaiController.java @@ -0,0 +1,731 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.vid.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.onap.portalsdk.core.controller.RestrictedBaseController; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.portalsdk.core.util.SystemProperties; +import org.onap.vid.aai.AaiGetVnfResponse; +import org.onap.vid.aai.AaiResponse; +import org.onap.vid.aai.AaiResponseTranslator.PortMirroringConfigData; +import org.onap.vid.aai.ServiceInstancesSearchResults; +import org.onap.vid.aai.SubscriberFilteredResults; +import org.onap.vid.aai.model.AaiGetInstanceGroupsByCloudRegion; +import org.onap.vid.aai.model.AaiGetOperationalEnvironments.OperationalEnvironmentList; +import org.onap.vid.aai.model.AaiGetPnfs.Pnf; +import org.onap.vid.aai.model.AaiGetTenatns.GetTenantsResponse; +import org.onap.vid.aai.util.AAIRestInterface; +import org.onap.vid.model.VersionByInvariantIdsRequest; +import org.onap.vid.roles.Role; +import org.onap.vid.roles.RoleProvider; +import org.onap.vid.roles.RoleValidator; +import org.onap.vid.services.AaiService; +import org.onap.vid.utils.Unchecked; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.HandlerMapping; +import org.springframework.web.servlet.ModelAndView; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.QueryParam; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; + +import static org.onap.vid.utils.Logging.getMethodName; + +/** + * Controller to handle a&ai requests. + */ + +@RestController +public class AaiController extends RestrictedBaseController { + + /** + * The from app id. + */ + private String fromAppId = "VidAaiController"; + /** + * The logger. + */ + private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(AaiController.class); + /** + * The model. + */ + private Map model = new HashMap<>(); + /** + * The servlet context. + */ + @Autowired + private ServletContext servletContext; + /** + * aai service + */ + @Autowired + private AaiService aaiService; + @Autowired + private RoleProvider roleProvider; + + @Autowired + private AAIRestInterface aaiRestInterface; + + /** + * Welcome method. + * + * @param request the request + * @return ModelAndView The view + */ + @RequestMapping(value = {"/subscriberSearch"}, method = RequestMethod.GET) + public ModelAndView welcome(HttpServletRequest request) { + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== AaiController welcome start"); + return new ModelAndView(getViewName()); + } + + @RequestMapping(value = {"/aai_get_aic_zones"}, method = RequestMethod.GET) + public ResponseEntity getAicZones(HttpServletRequest request) throws IOException { + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== getAicZones controller start"); + AaiResponse response = aaiService.getAaiZones(); + return aaiResponseToResponseEntity(response); + } + + @RequestMapping(value = {"/aai_get_aic_zone_for_pnf/{globalCustomerId}/{serviceType}/{serviceId}"}, method = RequestMethod.GET) + public ResponseEntity getAicZoneForPnf(@PathVariable("globalCustomerId") String globalCustomerId ,@PathVariable("serviceType") String serviceType , @PathVariable("serviceId") String serviceId ,HttpServletRequest request) throws IOException { + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== getAicZoneForPnf controller start"); + AaiResponse response = aaiService.getAicZoneForPnf(globalCustomerId , serviceType , serviceId); + return aaiResponseToResponseEntity(response); + } + + @RequestMapping(value = {"/aai_get_instance_groups_by_vnf_instance_id/{vnfInstanceId}"}, method = RequestMethod.GET) + public ResponseEntity getInstanceGroupsByVnfInstanceId(@PathVariable("vnfInstanceId") String vnfInstanceId ,HttpServletRequest request) throws IOException { + AaiResponse response = aaiService.getInstanceGroupsByVnfInstanceId(vnfInstanceId); + return aaiResponseToResponseEntity(response); + } + /** + * Get services from a&ai. + * + * @return ResponseEntity The response entity with the logged in user uuid. + * @throws IOException Signals that an I/O exception has occurred. + */ + @RequestMapping(value = {"/getuserID"}, method = RequestMethod.GET) + public ResponseEntity getUserID(HttpServletRequest request) { + + String userId = ControllersUtils.extractUserId(request); + + return new ResponseEntity<>(userId, HttpStatus.OK); + } + + /** + * Get services from a&ai. + * + * @return ResponseEntity The response entity + * @throws IOException Signals that an I/O exception has occurred. + */ + @RequestMapping(value = "/aai_get_services", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity doGetServices(HttpServletRequest request) throws IOException { + RoleValidator roleValidator = new RoleValidator(roleProvider.getUserRoles(request)); + + AaiResponse subscriberList = aaiService.getServices(roleValidator); + return aaiResponseToResponseEntity(subscriberList); + } + + + @RequestMapping(value = {"/aai_get_version_by_invariant_id"}, method = RequestMethod.POST) + public ResponseEntity getVersionByInvariantId(HttpServletRequest request, @RequestBody VersionByInvariantIdsRequest versions) { + Response result = aaiService.getVersionByInvariantId(versions.versions); + + return new ResponseEntity<>(result.readEntity(String.class), HttpStatus.OK); + } + + + private ResponseEntity aaiResponseToResponseEntity(AaiResponse aaiResponseData) + throws IOException { + ResponseEntity responseEntity; + ObjectMapper objectMapper = new ObjectMapper(); + if (aaiResponseData.getHttpCode() == 200) { + responseEntity = new ResponseEntity<>(objectMapper.writeValueAsString(aaiResponseData.getT()), HttpStatus.OK); + } else { + responseEntity = new ResponseEntity<>(aaiResponseData.getErrorMessage(), HttpStatus.valueOf(aaiResponseData.getHttpCode())); + } + return responseEntity; + } + + /** + * Lookup single service instance in a&ai. Get the service-subscription and customer, too, i guess? + * + * @param serviceInstanceId the service instance Id + * @return ResponseEntity The response entity + * @throws IOException Signals that an I/O exception has occurred. + */ + @RequestMapping(value = "/aai_get_service_instance/{service-instance-id}/{service-instance-type}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity doGetServiceInstance(@PathVariable("service-instance-id") String serviceInstanceId, @PathVariable("service-instance-type") String serviceInstanceType) { + Response resp = null; + + if (serviceInstanceType.equalsIgnoreCase("Service Instance Id")) { + resp = doAaiGet( + "search/nodes-query?search-node-type=service-instance&filter=service-instance-id:EQUALS:" + + serviceInstanceId, false); + } else { + resp = doAaiGet( + "search/nodes-query?search-node-type=service-instance&filter=service-instance-name:EQUALS:" + + serviceInstanceId, false); + } + return convertResponseToResponseEntity(resp); + } + + /** + * Get services from a&ai. + * + * @param globalCustomerId the global customer id + * @param serviceSubscriptionId the service subscription id + * @return ResponseEntity The response entity + * @throws IOException Signals that an I/O exception has occurred. + */ + @RequestMapping(value = "/aai_get_service_subscription/{global-customer-id}/{service-subscription-id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity doGetServices(@PathVariable("global-customer-id") String globalCustomerId, + @PathVariable("service-subscription-id") String serviceSubscriptionId) { + Response resp = doAaiGet("business/customers/customer/" + globalCustomerId + + "/service-subscriptions/service-subscription/" + serviceSubscriptionId + "?depth=0", false); + return convertResponseToResponseEntity(resp); + } + + /** + * Obtain the subscriber list from a&ai. + * + * @param fullSet the full set + * @return ResponseEntity The response entity + * @throws IOException Signals that an I/O exception has occurred. + */ + @RequestMapping(value = "/aai_get_subscribers", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity doGetSubscriberList(HttpServletRequest request, @DefaultValue("n") @QueryParam("fullSet") String fullSet) throws IOException { + return getFullSubscriberList(request); + } + + /** + * Obtain the Target Prov Status from the System.Properties file. + * + * @return ResponseEntity The response entity + * @throws IOException Signals that an I/O exception has occurred. + */ + @RequestMapping(value = "/get_system_prop_vnf_prov_status", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity getTargetProvStatus() { + String p = SystemProperties.getProperty("aai.vnf.provstatus"); + return new ResponseEntity<>(p, HttpStatus.OK); + } + + + /** + * Obtain the Target Prov Status from the System.Properties file. + * + * @return ResponseEntity The response entity + * @throws IOException Signals that an I/O exception has occurred. + */ + @RequestMapping(value = "/get_operational_environments", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + public AaiResponse getOperationalEnvironments(@RequestParam(value="operationalEnvironmentType", required = false) String operationalEnvironmentType, + @RequestParam(value="operationalEnvironmentStatus", required = false) String operationalEnvironmentStatus) { + LOGGER.debug(EELFLoggerDelegate.debugLogger, "start {}({}, {})", getMethodName(), operationalEnvironmentType, operationalEnvironmentStatus); + AaiResponse response = aaiService.getOperationalEnvironments(operationalEnvironmentType,operationalEnvironmentStatus); + if (response.getHttpCode() != 200) { + String errorMessage = getAaiErrorMessage(response.getErrorMessage()); + if(errorMessage != null) { + response = new AaiResponse<>(response.getT(), errorMessage, response.getHttpCode()); + } + } + + LOGGER.debug(EELFLoggerDelegate.debugLogger, "end {}() => {}", getMethodName(), response); + return response; + } + + /** + * Obtain the full subscriber list from a&ai. + *

+ * g @return ResponseEntity The response entity + * + * @throws IOException Signals that an I/O exception has occurred. + */ + @RequestMapping(value = "/aai_get_full_subscribers", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity getFullSubscriberList(HttpServletRequest request) throws IOException { + ObjectMapper objectMapper = new ObjectMapper(); + ResponseEntity responseEntity; + RoleValidator roleValidator = new RoleValidator(roleProvider.getUserRoles(request)); + SubscriberFilteredResults subscriberList = aaiService.getFullSubscriberList(roleValidator); + if (subscriberList.getHttpCode() == 200) { + responseEntity = new ResponseEntity<>(objectMapper.writeValueAsString(subscriberList.getSubscriberList()), HttpStatus.OK); + } else { + responseEntity = new ResponseEntity<>(subscriberList.getErrorMessage(), HttpStatus.valueOf(subscriberList.getHttpCode())); + } + + + return responseEntity; + } + + + @RequestMapping(value = "/get_vnf_data_by_globalid_and_service_type/{globalCustomerId}/{serviceType}", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity getVnfDataByGlobalIdAndServiceType(HttpServletRequest request, + @PathVariable("globalCustomerId") String globalCustomerId, + @PathVariable("serviceType") String serviceType) throws IOException { + + AaiResponse resp = aaiService.getVNFData(globalCustomerId, serviceType); + return aaiResponseToResponseEntity(resp); + } + + + /** + * Refresh the subscriber list from a&ai. + * + * @return ResponseEntity The response entity + * @throws IOException Signals that an I/O exception has occurred. + */ + @RequestMapping(value = "/aai_refresh_subscribers", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity doRefreshSubscriberList() { + return refreshSubscriberList(); + } + + /** + * Refresh the full subscriber list from a&ai. + * + * @return ResponseEntity The response entity + * @throws IOException Signals that an I/O exception has occurred. + */ + @RequestMapping(value = "/aai_refresh_full_subscribers", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity doRefreshFullSubscriberList() { + return refreshSubscriberList(); + } + + protected ResponseEntity refreshSubscriberList() { + Response resp = getSubscribers(); + return convertResponseToResponseEntity(resp); + } + + /** + * Get subscriber details from a&ai. + * + * @param subscriberId the subscriber id + * @return ResponseEntity The response entity + */ + @RequestMapping(value = "/aai_sub_details/{subscriberId}", method = RequestMethod.GET) + public ResponseEntity GetSubscriberDetails(HttpServletRequest request, @PathVariable("subscriberId") String subscriberId) throws IOException { + ObjectMapper objectMapper = new ObjectMapper(); + ResponseEntity responseEntity; + List roles = roleProvider.getUserRoles(request); + RoleValidator roleValidator = new RoleValidator(roles); + AaiResponse subscriberData = aaiService.getSubscriberData(subscriberId, roleValidator); + String httpMessage = subscriberData.getT() != null ? + objectMapper.writeValueAsString(subscriberData.getT()) : + subscriberData.getErrorMessage(); + + responseEntity = new ResponseEntity(httpMessage, HttpStatus.valueOf(subscriberData.getHttpCode())); + return responseEntity; + } + + /** + * Get service instances that match the query from a&ai. + * + * @param subscriberId the subscriber id + * @param instanceIdentifier the service instance name or id. + * @param projects the projects that are related to the instance + * @param owningEntities the owningEntities that are related to the instance + * @return ResponseEntity The response entity + */ + @RequestMapping(value = "/search_service_instances", method = RequestMethod.GET) + public ResponseEntity SearchServiceInstances(HttpServletRequest request, + @RequestParam(value="subscriberId", required = false) String subscriberId, + @RequestParam(value="serviceInstanceIdentifier", required = false) String instanceIdentifier, + @RequestParam(value="project", required = false) List projects, + @RequestParam(value="owningEntity", required = false) List owningEntities) throws IOException { + ObjectMapper objectMapper = new ObjectMapper(); + ResponseEntity responseEntity; + + List roles = roleProvider.getUserRoles(request); + RoleValidator roleValidator = new RoleValidator(roles); + + AaiResponse searchResult = aaiService.getServiceInstanceSearchResults(subscriberId, instanceIdentifier, roleValidator, owningEntities, projects); + + String httpMessage = searchResult.getT() != null ? + objectMapper.writeValueAsString(searchResult.getT()) : + searchResult.getErrorMessage(); + + + if(searchResult.getT().serviceInstances.isEmpty()){ + responseEntity = new ResponseEntity(httpMessage, HttpStatus.NOT_FOUND); + + } else { + responseEntity = new ResponseEntity(httpMessage, HttpStatus.valueOf(searchResult.getHttpCode())); + + } + return responseEntity; + } + + + + /** + * Issue a named query to a&ai. + * + * @param namedQueryId the named query id + * @param globalCustomerId the global customer id + * @param serviceType the service type + * @param serviceInstance the service instance + * @return ResponseEntity The response entity + */ + @RequestMapping(value = "/aai_sub_viewedit/{namedQueryId}/{globalCustomerId}/{serviceType}/{serviceInstance}", method = RequestMethod.GET) + public ResponseEntity viewEditGetComponentList( + @PathVariable("namedQueryId") String namedQueryId, + @PathVariable("globalCustomerId") String globalCustomerId, + @PathVariable("serviceType") String serviceType, + @PathVariable("serviceInstance") String serviceInstance) { + + String componentListPayload = getComponentListPutPayload(namedQueryId, globalCustomerId, serviceType, serviceInstance); + + Response resp = doAaiPost("search/named-query", componentListPayload, false); + return convertResponseToResponseEntity(resp); + } + + /** + * Issue a named query to a&ai. + * + * @param namedQueryId the named query id + * @param globalCustomerId the global customer id + * @param serviceType the service type + * @return ResponseEntity The response entity + */ + @RequestMapping(value = "/aai_get_models_by_service_type/{namedQueryId}/{globalCustomerId}/{serviceType}", method = RequestMethod.GET) + public ResponseEntity viewEditGetComponentList( + @PathVariable("namedQueryId") String namedQueryId, + @PathVariable("globalCustomerId") String globalCustomerId, + @PathVariable("serviceType") String serviceType) { + + String componentListPayload = getModelsByServiceTypePayload(namedQueryId, globalCustomerId, serviceType); + + Response resp = doAaiPost("search/named-query", componentListPayload, false); + return convertResponseToResponseEntity(resp); + } + + @RequestMapping(value = "/aai_get_vnf_instances/{globalCustomerId}/{serviceType}/{modelVersionId}/{modelInvariantId}/{cloudRegion}", method = RequestMethod.GET) + public ResponseEntity getNodeTemplateInstances( + @PathVariable("globalCustomerId") String globalCustomerId, + @PathVariable("serviceType") String serviceType, + @PathVariable("modelVersionId") String modelVersionId, + @PathVariable("modelInvariantId") String modelInvariantId, + @PathVariable("cloudRegion") String cloudRegion) { + + AaiResponse resp = aaiService.getNodeTemplateInstances(globalCustomerId, serviceType, modelVersionId, modelInvariantId, cloudRegion); + return new ResponseEntity<>(resp.getT(), HttpStatus.valueOf(resp.getHttpCode())); + } + + @RequestMapping(value = "/aai_get_network_collection_details/{serviceInstanceId}", method = RequestMethod.GET) + public ResponseEntity getNetworkCollectionDetails(@PathVariable("serviceInstanceId") String serviceInstanceId) throws IOException { + com.fasterxml.jackson.databind.ObjectMapper objectMapper = new com.fasterxml.jackson.databind.ObjectMapper(); + AaiResponse resp = aaiService.getNetworkCollectionDetails(serviceInstanceId); + + String httpMessage = resp.getT() != null ? + objectMapper.writeValueAsString(resp.getT()) : + resp.getErrorMessage(); + return new ResponseEntity<>(httpMessage, HttpStatus.valueOf(resp.getHttpCode())); + } + + @RequestMapping(value = "/aai_get_instance_groups_by_cloudregion/{cloudOwner}/{cloudRegionId}/{networkFunction}", method = RequestMethod.GET) + public ResponseEntity getInstanceGroupsByCloudRegion(@PathVariable("cloudOwner") String cloudOwner, + @PathVariable("cloudRegionId") String cloudRegionId, + @PathVariable("networkFunction") String networkFunction) throws IOException { + com.fasterxml.jackson.databind.ObjectMapper objectMapper = new com.fasterxml.jackson.databind.ObjectMapper(); + AaiResponse resp = aaiService.getInstanceGroupsByCloudRegion(cloudOwner, cloudRegionId, networkFunction); + + String httpMessage = resp.getT() != null ? + objectMapper.writeValueAsString(resp.getT()) : + resp.getErrorMessage(); + return new ResponseEntity<>(httpMessage, HttpStatus.valueOf(resp.getHttpCode())); + } + + @RequestMapping(value = "/aai_get_by_uri/**", method = RequestMethod.GET) + public ResponseEntity getByUri(HttpServletRequest request) { + + String restOfTheUrl = (String) request.getAttribute( + HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE); + String formattedUri = restOfTheUrl.replaceFirst("/aai_get_by_uri/", "").replaceFirst("^aai/v[\\d]+/", ""); + + Response resp = doAaiGet(formattedUri, false); + + return convertResponseToResponseEntity(resp); + } + + + + @RequestMapping(value = "/aai_get_configuration/{configuration_id}", method = RequestMethod.GET) + public ResponseEntity getSpecificConfiguration(@PathVariable("configuration_id") String configurationId) { + + Response resp = doAaiGet("network/configurations/configuration/"+configurationId, false); + + return convertResponseToResponseEntity(resp); + } + + @RequestMapping(value = "/aai_get_service_instance_pnfs/{globalCustomerId}/{serviceType}/{serviceInstanceId}", method = RequestMethod.GET) + public List getServiceInstanceAssociatedPnfs( + @PathVariable("globalCustomerId") String globalCustomerId, + @PathVariable("serviceType") String serviceType, + @PathVariable("serviceInstanceId") String serviceInstanceId) { + + return aaiService.getServiceInstanceAssociatedPnfs(globalCustomerId, serviceType, serviceInstanceId); + } + + /** + * PNF section + */ + @RequestMapping(value = "/aai_get_pnfs/pnf/{pnf_id}", method = RequestMethod.GET) + public ResponseEntity getSpecificPnf(@PathVariable("pnf_id") String pnfId) { + AaiResponse resp; + ResponseEntity re; + try { + resp = aaiService.getSpecificPnf(pnfId); + re = new ResponseEntity<>(resp.getT(), HttpStatus.valueOf(resp.getHttpCode())); + } catch (Exception e){ + return new ResponseEntity(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + return re; + } + + + /** + * Obtain tenants for a given service type. + * + * @param globalCustomerId the global customer id + * @param serviceType the service type + * @return ResponseEntity The response entity + */ + @RequestMapping(value = "/aai_get_tenants/{global-customer-id}/{service-type}", method = RequestMethod.GET) + public ResponseEntity viewEditGetTenantsFromServiceType(HttpServletRequest request, + @PathVariable("global-customer-id") String globalCustomerId, @PathVariable("service-type") String serviceType) { + + ResponseEntity responseEntity; + try { + ObjectMapper objectMapper = new ObjectMapper(); + List roles = roleProvider.getUserRoles(request); + RoleValidator roleValidator = new RoleValidator(roles); + AaiResponse response = aaiService.getTenants(globalCustomerId, serviceType, roleValidator); + if (response.getHttpCode() == 200) { + responseEntity = new ResponseEntity(objectMapper.writeValueAsString(response.getT()), HttpStatus.OK); + } else { + responseEntity = new ResponseEntity(response.getErrorMessage(), HttpStatus.valueOf(response.getHttpCode())); + } + } catch (Exception e) { + responseEntity = new ResponseEntity("Unable to proccess getTenants reponse", HttpStatus.INTERNAL_SERVER_ERROR); + } + return responseEntity; + } + + @RequestMapping(value = "/aai_get_pnf_instances/{globalCustomerId}/{serviceType}/{modelVersionId}/{modelInvariantId}/{cloudRegion}/{equipVendor}/{equipModel}", method = RequestMethod.GET) + public ResponseEntity getPnfInstances( + @PathVariable("globalCustomerId") String globalCustomerId, + @PathVariable("serviceType") String serviceType, + @PathVariable("modelVersionId") String modelVersionId, + @PathVariable("modelInvariantId") String modelInvariantId, + @PathVariable("cloudRegion") String cloudRegion, + @PathVariable("equipVendor") String equipVendor, + @PathVariable("equipModel") String equipModel) { + + AaiResponse resp = aaiService.getPNFData(globalCustomerId, serviceType, modelVersionId, modelInvariantId, cloudRegion, equipVendor, equipModel); + return new ResponseEntity<>(resp.getT(), HttpStatus.valueOf(resp.getHttpCode())); + } + + @RequestMapping(value = "/aai_getPortMirroringConfigsData", method = RequestMethod.GET) + public Map getPortMirroringConfigsData( + @RequestParam ("configurationIds") List configurationIds) { + + return configurationIds.stream() + .map(id -> ImmutablePair.of(id, aaiService.getPortMirroringConfigData(id))) + .collect(Collectors.toMap(Pair::getKey, Pair::getValue)); + } + + @RequestMapping(value = "/aai_getPortMirroringSourcePorts", method = RequestMethod.GET) + public Map getPortMirroringSourcePorts( + @RequestParam ("configurationIds") List configurationIds) { + + return configurationIds.stream() + .map(id -> ImmutablePair.of(id, aaiService.getPortMirroringSourcePorts(id))) + .collect(Collectors.toMap(Pair::getKey, Pair::getValue)); + } + + private ResponseEntity convertResponseToResponseEntity(Response resp) { + ResponseEntity respEnt; + if (resp == null) { + respEnt = new ResponseEntity<>("Failed to fetch data from A&AI, check server logs for details.", HttpStatus.INTERNAL_SERVER_ERROR); + } else { + respEnt = new ResponseEntity<>(resp.readEntity(String.class), HttpStatus.valueOf(resp.getStatus())); + } + return respEnt; + } + + /** + * Gets the subscribers. + * + * @return the subscribers + */ + private Response getSubscribers() { + + String depth = "0"; + + Response resp = doAaiGet("business/customers?subscriber-type=INFRA&depth=" + depth, false); + if (resp != null) { + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== getSubscribers() resp=" + resp.getStatusInfo().toString()); + } + return resp; + } + + /** + * Send a GET request to a&ai. + * + * @param uri the uri + * @param xml the xml + * @return String The response + */ + protected Response doAaiGet(String uri, boolean xml) { + String methodName = "getSubscriberList"; + String transId = UUID.randomUUID().toString(); + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + " start"); + + Response resp = null; + try { + + + resp = aaiRestInterface.RestGet(fromAppId, transId, Unchecked.toURI(uri), xml).getResponse(); + + } catch (WebApplicationException e) { + final String message = e.getResponse().readEntity(String.class); + LOGGER.info(EELFLoggerDelegate.errorLogger, "<== " + "." + methodName + message); + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + "." + methodName + message); + } catch (Exception e) { + LOGGER.info(EELFLoggerDelegate.errorLogger, "<== " + "." + methodName + e.toString()); + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + "." + methodName + e.toString()); + } + + return resp; + } + + /** + * Send a POST request to a&ai. + * + * @param uri the uri + * @param payload the payload + * @param xml the xml + * @return String The response + */ + protected Response doAaiPost(String uri, String payload, boolean xml) { + String methodName = "getSubscriberList"; + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + " start"); + + Response resp = null; + try { + + resp = aaiRestInterface.RestPost(fromAppId, uri, payload, xml); + + } catch (Exception e) { + LOGGER.info(EELFLoggerDelegate.errorLogger, "<== " + "." + methodName + e.toString()); + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + "." + methodName + e.toString()); + } + + return resp; + } + + /** + * Gets the component list put payload. + * + * @param namedQueryId the named query id + * @param globalCustomerId the global customer id + * @param serviceType the service type + * @param serviceInstance the service instance + * @return the component list put payload + */ + private String getComponentListPutPayload(String namedQueryId, String globalCustomerId, String serviceType, String serviceInstance) { + return + " {" + + " \"instance-filters\": {" + + " \"instance-filter\": [" + + " {" + + " \"customer\": {" + + " \"global-customer-id\": \"" + globalCustomerId + "\"" + + " }," + + " \"service-instance\": {" + + " \"service-instance-id\": \"" + serviceInstance + "\"" + + " }," + + " \"service-subscription\": {" + + " \"service-type\": \"" + serviceType + "\"" + + " }" + + " }" + + " ]" + + " }," + + " \"query-parameters\": {" + + " \"named-query\": {" + + " \"named-query-uuid\": \"" + namedQueryId + "\"" + + " }" + + " }" + + "}"; + + } + + private String getModelsByServiceTypePayload(String namedQueryId, String globalCustomerId, String serviceType) { + // TODO Auto-generated method stub + return " {" + + " \"instance-filters\": {" + + " \"instance-filter\": [" + + " {" + + " \"customer\": {" + + " \"global-customer-id\": \"" + globalCustomerId + "\"" + + " }," + + " \"service-subscription\": {" + + " \"service-type\": \"" + serviceType + "\"" + + " }" + + " }" + + " ]" + + " }," + + " \"query-parameters\": {" + + " \"named-query\": {" + + " \"named-query-uuid\": \"" + namedQueryId + "\"" + + " }" + + " }" + + "}"; + + } + + private String getAaiErrorMessage(String message) { + try { + org.json.JSONObject json = new org.json.JSONObject(message); + json = json.getJSONObject("requestError").getJSONObject("serviceException"); + + return json.getString("messageId") + ": " + json.getString("text"); + + } catch (Exception e) { + return null; + } + } +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/AaiController2.java b/vid-app-common/src/main/java/org/onap/vid/controller/AaiController2.java new file mode 100644 index 000000000..ee287703c --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/controller/AaiController2.java @@ -0,0 +1,98 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.vid.controller; + +import org.onap.vid.aai.AaiClientInterface; +import org.onap.vid.aai.model.AaiGetTenatns.GetTenantsResponse; +import org.onap.vid.aai.model.Permissions; +import org.onap.vid.model.aaiTree.RelatedVnf; +import org.onap.vid.roles.RoleProvider; +import org.onap.vid.services.AaiService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.util.List; + +/** + * Controller to handle a&ai new requests. + */ + +@RestController +public class AaiController2 extends VidRestrictedBaseController { + + private final AaiService aaiService; + private final RoleProvider roleProvider; + private final AaiClientInterface aaiClient; + + @Autowired + public AaiController2(AaiService aaiService, RoleProvider roleProvider, AaiClientInterface aaiClient) { + this.aaiService = aaiService; + this.roleProvider = roleProvider; + this.aaiClient = aaiClient; + } + + @RequestMapping(value = "/aai_get_homing_by_vfmodule/{vnfInstanceId}/{vfModuleId}", method = RequestMethod.GET) + public GetTenantsResponse getHomingDataByVfModule(@PathVariable("vnfInstanceId") String vnfInstanceId, + @PathVariable("vfModuleId") String vfModuleId){ + return aaiService.getHomingDataByVfModule(vnfInstanceId, vfModuleId); + } + + @RequestMapping(value = "/aai_get_service_instance_topology/{subscriberId}/{serviceType}/{serviceInstanceId}", + method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + public String getServiceInstanceTree(@PathVariable("subscriberId") String globalCustomerId, + @PathVariable("serviceType") String serviceInstanceType, + @PathVariable("serviceInstanceId") String serviceInstanceId) { + return aaiService.getAAIServiceTree(globalCustomerId, serviceInstanceType, serviceInstanceId); + } + + @RequestMapping(value = "/aai_reset_cache/{cacheName}", method = RequestMethod.DELETE) + @ResponseStatus(HttpStatus.ACCEPTED) + public void resetCache(@PathVariable("cacheName") String cacheName) { + aaiClient.resetCache(cacheName); + } + + @RequestMapping(value = "/roles/service_permissions", method = RequestMethod.GET) + public Permissions servicePermissions(HttpServletRequest request, + @RequestParam(value = "subscriberId") String subscriberId, + @RequestParam(value = "serviceType") String serviceType) { + + final boolean isEditPermitted = roleProvider + .getUserRolesValidator(request) + .isServicePermitted(subscriberId, serviceType); + + return new Permissions(isEditPermitted); + } + + @RequestMapping(value = "/aai_search_group_members", + method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + public List searchGroupMembers(@RequestParam("subscriberId") String globalCustomerId, + @RequestParam("serviceType") String serviceType, + @RequestParam("serviceInvariantId") String invariantId, + @RequestParam("groupType") String groupType, + @RequestParam("groupRole") String groupRole) { + return aaiService.searchGroupMembers(globalCustomerId, serviceType, invariantId, groupType, groupRole); + } + + +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/AaiServiceInstanceStandardQueryController.java b/vid-app-common/src/main/java/org/onap/vid/controller/AaiServiceInstanceStandardQueryController.java new file mode 100644 index 000000000..974ac9883 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/controller/AaiServiceInstanceStandardQueryController.java @@ -0,0 +1,173 @@ +package org.onap.vid.controller; + + +import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Network; +import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.ServiceInstance; +import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Vlan; +import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Vnf; +import org.onap.vid.aai.util.ServiceInstanceStandardQuery; +import org.onap.vid.asdc.AsdcCatalogException; +import org.onap.vid.exceptions.GenericUncheckedException; +import org.onap.vid.model.ServiceModel; +import org.onap.vid.model.VidNotions; +import org.onap.vid.properties.Features; +import org.onap.vid.services.VidService; +import org.onap.vid.utils.Multival; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.togglz.core.manager.FeatureManager; + +import javax.servlet.http.HttpServletRequest; +import java.util.Collection; +import java.util.Collections; +import java.util.UUID; + +import static java.util.stream.Collectors.toList; + + +@RestController +@RequestMapping(AaiServiceInstanceStandardQueryController.AAI_STANDARD_QUERY) +public class AaiServiceInstanceStandardQueryController extends VidRestrictedBaseController { + + public static final String AAI_STANDARD_QUERY = "aai/standardQuery"; + + private final ServiceInstanceStandardQuery serviceInstanceStandardQuery; + private final FeatureManager featureManager; + private final VidService sdcService; + + @Autowired + public AaiServiceInstanceStandardQueryController(FeatureManager featureManager, ServiceInstanceStandardQuery serviceInstanceStandardQuery, VidService sdcService) { + this.featureManager = featureManager; + this.serviceInstanceStandardQuery = serviceInstanceStandardQuery; + this.sdcService = sdcService; + } + + @RequestMapping(value = "vlansByNetworks", method = RequestMethod.GET) + public VlansByNetworksHierarchy getNetworksToVlansByServiceInstance(HttpServletRequest request, + @RequestParam("sdcModelUuid") UUID sdcModelUuid, + @RequestParam("globalCustomerId") String globalCustomerId, + @RequestParam("serviceType") String serviceType, + @RequestParam("serviceInstanceId") String serviceInstanceId + ) throws AsdcCatalogException { + if (!featureManager.isActive(Features.FLAG_PRESENT_PROVIDER_NETWORKS_ASSOCIATIONS)) { + return new VlansByNetworksHierarchy(); + } + + if (!isModelOf5g(sdcModelUuid)) { + return new VlansByNetworksHierarchy(); + } + + final ServiceInstance serviceInstance = + serviceInstanceStandardQuery.fetchServiceInstance(globalCustomerId, serviceType, serviceInstanceId); + + Multival>> l3NetworksWithVlansForVnfForService = fetchVnfsForService(serviceInstance); + Multival> l3NetworksWithVlansForService = fetchNetworksForService(serviceInstance); + + // translate to response's format + return new VlansByNetworksHierarchy( + l3NetworksWithVlansForService.getValues().stream().map(this::translateNetworksFormat + ).collect(toList()), + + l3NetworksWithVlansForVnfForService.getValues().stream().map(vnfWithNetworks -> + new VnfVlansByNetworks(vnfWithNetworks.getKey().getVnfId(), + vnfWithNetworks.getValues().stream().map(this::translateNetworksFormat + ).collect(toList()) + ) + ).collect(toList()) + ); + } + + private Multival>> fetchVnfsForService(ServiceInstance serviceInstance) { + final Multival vnfsForService = + serviceInstanceStandardQuery.fetchRelatedVnfs(serviceInstance); + + final Multival> vnfsWithL3NetworksForService = + vnfsForService.mapEachVal(vnf -> serviceInstanceStandardQuery.fetchRelatedL3Networks("vnf", vnf)); + + return vnfsWithL3NetworksForService.mapEachVal(vnfMulti-> + vnfMulti.mapEachVal(serviceInstanceStandardQuery::fetchRelatedVlanTags) + ); + + } + + private Multival> fetchNetworksForService(ServiceInstance serviceInstance) { + final Multival l3NetworksForService = + serviceInstanceStandardQuery.fetchRelatedL3Networks("service", serviceInstance); + + return l3NetworksForService.mapEachVal(serviceInstanceStandardQuery::fetchRelatedVlanTags); + } + + private NetworksToVlans translateNetworksFormat(Multival networkWithVlan) { + return new NetworksToVlans( + networkWithVlan.getKey().getNetworkId(), + networkWithVlan.getKey().getNetworkName(), + networkWithVlan.getKey().getNetworkType(), + networkWithVlan.getKey().getOrchestrationStatus(), + networkWithVlan.getValues().stream().map( + vlan -> new NetworksToVlans.Vlan(vlan.getVlanIdInner()) + ).collect(toList()) + ); + } + + protected boolean isModelOf5g(UUID sdcModelUuid) throws AsdcCatalogException { + final ServiceModel serviceModel = sdcService.getService(sdcModelUuid.toString()); + if (serviceModel == null) { + throw new GenericUncheckedException("Internal error while fetching Service Model: " + sdcModelUuid); + } + VidNotions.ModelCategory serviceModelCategory = serviceModel.getService().getVidNotions().getModelCategory(); + return serviceModelCategory.equals(VidNotions.ModelCategory.IS_5G_PROVIDER_NETWORK_MODEL) || + serviceModelCategory.equals(VidNotions.ModelCategory.IS_5G_FABRIC_CONFIGURATION_MODEL); + } + + protected static class VlansByNetworksHierarchy { + public final Collection serviceNetworks; + public final Collection vnfNetworks; + + public VlansByNetworksHierarchy() { + this(Collections.emptySet(), Collections.emptySet()); + } + + public VlansByNetworksHierarchy(Collection serviceNetworks, Collection vnfNetworks) { + this.serviceNetworks = serviceNetworks; + this.vnfNetworks = vnfNetworks; + } + } + + protected static class VnfVlansByNetworks { + public final String vnfId; + public final Collection networks; + + public VnfVlansByNetworks(String vnfId, Collection networks) { + this.vnfId = vnfId; + this.networks = networks; + } + } + + protected static class NetworksToVlans { + public final String networkId; + public final String name; + public final String nodeType; + public final String nodeStatus; + public final Collection vlans; + + private NetworksToVlans(String networkId, String name, String nodeType, String nodeStatus, Collection vlans) { + this.networkId = networkId; + this.name = name; + this.nodeType = nodeType; + this.nodeStatus = nodeStatus; + this.vlans = vlans; + } + + private static class Vlan { + public final String vlanIdInner; + + private Vlan(String vlanIdInner) { + this.vlanIdInner = vlanIdInner; + } + } + + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/AsyncControllerForTests.java b/vid-app-common/src/main/java/org/onap/vid/controller/AsyncControllerForTests.java new file mode 100644 index 000000000..a67686a90 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/controller/AsyncControllerForTests.java @@ -0,0 +1,48 @@ +package org.onap.vid.controller; + +import org.onap.vid.exceptions.GenericUncheckedException; +import org.onap.vid.model.ExceptionResponse; +import org.onap.vid.model.JobModel; +import org.onap.vid.services.BulkInstantiationService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import javax.ws.rs.WebApplicationException; +import java.util.UUID; + +import static org.springframework.http.HttpStatus.BAD_REQUEST; + +@RestController +@RequestMapping("asyncForTests") +public class AsyncControllerForTests extends VidRestrictedBaseController { + + private BulkInstantiationService bulkInstantiationService; + + @Autowired + public AsyncControllerForTests(BulkInstantiationService bulkInstantiationService) { + this.bulkInstantiationService = bulkInstantiationService; + } + + @RequestMapping(value = "/job/{uuid}", method = RequestMethod.GET) + public JobModel getJob(@PathVariable UUID uuid) { + return bulkInstantiationService.getJob(uuid); + } + + @RequestMapping(value = "/error", method = RequestMethod.GET) + public void throwError() { + throw new GenericUncheckedException("dummy error"); + } + + @ExceptionHandler({IllegalArgumentException.class}) + @ResponseStatus(value=BAD_REQUEST) + private ExceptionResponse exceptionHandlerBadRequest(Exception e) { + return ControllersUtils.handleException(e, LOGGER); + } + + @ExceptionHandler(WebApplicationException.class) + private ResponseEntity webApplicationExceptionHandler(WebApplicationException e) { + return ControllersUtils.handleWebApplicationException(e, LOGGER); + } + +} diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/AsyncInstantiationController.java b/vid-app-common/src/main/java/org/onap/vid/controller/AsyncInstantiationController.java new file mode 100644 index 000000000..dcfc13b3b --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/controller/AsyncInstantiationController.java @@ -0,0 +1,104 @@ +package org.onap.vid.controller; + + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.vid.exceptions.OperationNotAllowedException; +import org.onap.vid.model.ExceptionResponse; +import org.onap.vid.model.JobAuditStatus; +import org.onap.vid.model.ServiceInfo; +import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; +import org.onap.vid.mso.MsoResponseWrapper2; +import org.onap.vid.services.AsyncInstantiationBusinessLogic; +import org.onap.vid.services.AuditService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.util.List; +import java.util.UUID; + +import static org.springframework.http.HttpStatus.METHOD_NOT_ALLOWED; + + +@RestController +@RequestMapping(AsyncInstantiationController.ASYNC_INSTANTIATION) +public class AsyncInstantiationController extends VidRestrictedBaseController { + + public static final String ASYNC_INSTANTIATION = "asyncInstantiation"; + + protected final AsyncInstantiationBusinessLogic asyncInstantiationBL; + + protected ObjectMapper objectMapper = new ObjectMapper(); + + @Autowired + protected AuditService auditService; + + @Autowired + public AsyncInstantiationController(AsyncInstantiationBusinessLogic asyncInstantiationBL) { + this.asyncInstantiationBL = asyncInstantiationBL; + } + + @ExceptionHandler(OperationNotAllowedException.class) + @ResponseStatus(value=METHOD_NOT_ALLOWED) + public ExceptionResponse illegalStateExceptionHandler(Exception e) { + return ControllersUtils.handleException(e, LOGGER); + } + + /** + * Gets the new services status. + * @param request the request + * @return the services list + */ + @RequestMapping(method = RequestMethod.GET) + public List getServicesInfo(HttpServletRequest request) { + return asyncInstantiationBL.getAllServicesInfo(); + } + + @RequestMapping(value = "bulk", method = RequestMethod.POST) + public MsoResponseWrapper2> createBulkOfServices(@RequestBody ServiceInstantiation request, HttpServletRequest httpServletRequest) { + //Push to DB according the model + try { + LOGGER.debug(EELFLoggerDelegate.debugLogger, "incoming ServiceInstantiation request: "+ objectMapper.writeValueAsString(request)); + } + catch (Exception e) { + LOGGER.error(EELFLoggerDelegate.errorLogger, "failed to log incoming ServiceInstantiation request ", e); + } + String userId = ControllersUtils.extractUserId(httpServletRequest); + List uuids = asyncInstantiationBL.pushBulkJob(request, userId); + + return new MsoResponseWrapper2(200, uuids); + } + + @RequestMapping(value = "job/{jobId}", method = RequestMethod.DELETE) + public void deleteServiceInfo(@PathVariable("jobId") UUID jobId) { + asyncInstantiationBL.deleteJob(jobId); + } + + @RequestMapping(value = "hide/{jobId}", method = RequestMethod.POST) + public void hideServiceInfo(@PathVariable("jobId") UUID jobId) { + asyncInstantiationBL.hideServiceInfo(jobId); + } + + @RequestMapping(value = "auditStatus/{jobId}", method = RequestMethod.GET) + public List getJobAuditStatus(HttpServletRequest request, @PathVariable(value="jobId") UUID jobId, @RequestParam(value="source") JobAuditStatus.SourceStatus source){ + return asyncInstantiationBL.getAuditStatuses(jobId, source); + } + + @RequestMapping(value = "auditStatus/{jobId}/mso", method = RequestMethod.GET) + public List getJobMsoAuditStatusForAlaCarte(HttpServletRequest request, + @PathVariable(value="jobId") UUID jobId, + @RequestParam(value="requestId", required = false) UUID requestId, + @RequestParam(value="serviceInstanceId", required = false) UUID serviceInstanceId){ + if (serviceInstanceId != null) { + return auditService.getAuditStatusFromMsoByServiceInstanceId(jobId, serviceInstanceId); + } + if (requestId != null){ + return auditService.getAuditStatusFromMsoByRequestId(jobId, requestId); + } + return auditService.getAuditStatusFromMsoByJobId(jobId); + + } + + +} diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/ChangeManagementController.java b/vid-app-common/src/main/java/org/onap/vid/controller/ChangeManagementController.java new file mode 100644 index 000000000..90a175f65 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/controller/ChangeManagementController.java @@ -0,0 +1,213 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright © 2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Modifications Copyright 2018 Nokia + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.vid.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.apache.commons.lang3.tuple.Pair; +import org.onap.portalsdk.core.controller.UnRestrictedBaseController; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.vid.changeManagement.*; +import org.onap.vid.exceptions.NotFoundException; +import org.onap.vid.model.ExceptionResponse; +import org.onap.vid.model.MsoExceptionResponse; +import org.onap.vid.mso.MsoResponseWrapper2; +import org.onap.vid.mso.MsoResponseWrapperInterface; +import org.onap.vid.mso.rest.Request; +import org.onap.vid.services.ChangeManagementService; +import org.onap.vid.services.WorkflowService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.WebApplicationException; +import java.util.Collection; +import java.util.Collections; + +import static org.onap.vid.utils.Logging.getMethodName; +import static org.springframework.http.HttpStatus.*; + +/** + * Controller to handle ChangeManagement feature requests. + */ +@RestController +@RequestMapping(ChangeManagementController.CHANGE_MANAGEMENT) +public class ChangeManagementController extends UnRestrictedBaseController { + public static final String VNF_WORKFLOW_RELATION = "vnf_workflow_relation"; + public static final String CHANGE_MANAGEMENT = "change-management"; + public static final String GET_VNF_WORKFLOW_RELATION = "get_vnf_workflow_relation"; + public static final String SCHEDULER_BY_SCHEDULE_ID = "/scheduler/schedules/{scheduleId}"; + private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(ChangeManagementController.class); + private String fromAppId; + private final WorkflowService workflowService; + private final ChangeManagementService changeManagementService; + private final ObjectMapper objectMapper; + + + @Autowired + public ChangeManagementController(WorkflowService workflowService, ChangeManagementService changeManagementService, ObjectMapper objectMapper) { + this.fromAppId = "VidChangeManagementController"; + this.workflowService = workflowService; + this.changeManagementService = changeManagementService; + this.objectMapper = objectMapper; + } + + @RequestMapping(value = {"/workflow"}, method = RequestMethod.GET) + public ResponseEntity> getWorkflow(@RequestParam("vnfs") Collection vnfs) { + Collection result = this.workflowService.getWorkflowsForVNFs(vnfs); + return new ResponseEntity<>(result, OK); + } + + @RequestMapping(value = {"/mso"}, method = RequestMethod.GET) + public ResponseEntity> getMSOChangeManagements() { + + Collection result = this.changeManagementService.getMSOChangeManagements(); + return new ResponseEntity<>(result, OK); + } + + @RequestMapping(value = "/workflow/{vnfName}", method = RequestMethod.POST) + public ResponseEntity changeManagement(HttpServletRequest request, + @PathVariable("vnfName") String vnfName, + @RequestBody ChangeManagementRequest changeManagmentRequest) + throws Exception { + return this.changeManagementService.doChangeManagement(changeManagmentRequest, vnfName); + } + + @RequestMapping(value = "/uploadConfigUpdateFile", method = RequestMethod.POST) + public @ResponseBody ResponseEntity uploadConfigUpdateFile(@RequestPart("file") MultipartFile file) + throws Exception { + try { + String jsonString = this.changeManagementService.uploadConfigUpdateFile(file); + return new ResponseEntity<>(jsonString, HttpStatus.OK); + } + catch(WebApplicationException e){ + return new ResponseEntity<>(handleException(e), HttpStatus.valueOf(e.getResponse().getStatus())); + } + catch (Exception e) { + return new ResponseEntity<>(handleException(e), INTERNAL_SERVER_ERROR); + } + } + + + @RequestMapping(value = {"/scheduler"}, method = RequestMethod.GET) + public ResponseEntity getSchedulerChangeManagements() { + ArrayNode result = this.changeManagementService.getSchedulerChangeManagements(); + return new ResponseEntity<>(result, OK); + } + + @RequestMapping(value = {SCHEDULER_BY_SCHEDULE_ID}, method = RequestMethod.DELETE) + public ResponseEntity deleteSchedule(@PathVariable("scheduleId") String scheduleId) { + Pair result = this.changeManagementService.deleteSchedule(scheduleId); + return ResponseEntity.status(result.getRight()).build(); + } + + + @RequestMapping(value = {GET_VNF_WORKFLOW_RELATION}, method = RequestMethod.POST) + public ResponseEntity getWorkflows(@RequestBody GetVnfWorkflowRelationRequest getVnfWorkflowRelationRequest) { + try { + GetWorkflowsResponse response = new GetWorkflowsResponse(changeManagementService.getWorkflowsForVnf(getVnfWorkflowRelationRequest)); + return ResponseEntity.status(OK).body(response); + } + catch (NotFoundException exception) { + LOGGER.error(exception.getMessage(), exception); + return new ResponseEntity<>(new VnfWorkflowRelationResponse(Collections.singletonList(exception.getMessage())),HttpStatus.NOT_FOUND); + } + catch (Exception exception) { + return handleException(exception, "Failed to get workflows for vnf"); + } + } + + @RequestMapping(value = {VNF_WORKFLOW_RELATION}, method = RequestMethod.POST) + public ResponseEntity createWorkflowRelation(@RequestBody VnfWorkflowRelationRequest vnfWorkflowRelationRequest) { + VnfWorkflowRelationResponse vnfWorkflowRelationResponse; + try { + vnfWorkflowRelationResponse = changeManagementService.addVnfWorkflowRelation(vnfWorkflowRelationRequest); + } + catch (Exception exception) { + return handleException(exception, "Failed to add vnf to workflow relation"); + } + + return new ResponseEntity<>(vnfWorkflowRelationResponse, OK); + } + + @RequestMapping(value = {VNF_WORKFLOW_RELATION}, method = RequestMethod.GET) + public ResponseEntity getAllWorkflowRelation() { + + try { + VnfWorkflowRelationAllResponse vnfWorkflowRelationAllResponse = changeManagementService.getAllVnfWorkflowRelations(); + return new ResponseEntity<>(vnfWorkflowRelationAllResponse, OK); + } + catch (Exception exception) { + return handleException(exception, "Failed to get all vnf to workflow relations"); + } + } + + @RequestMapping(value = {VNF_WORKFLOW_RELATION}, method = RequestMethod.DELETE) + public ResponseEntity deleteWorkflowRelation(@RequestBody VnfWorkflowRelationRequest vnfWorkflowRelationRequest) { + VnfWorkflowRelationResponse vnfWorkflowRelationResponse; + try { + vnfWorkflowRelationResponse = changeManagementService.deleteVnfWorkflowRelation(vnfWorkflowRelationRequest); + } + catch (Exception exception) { + return handleException(exception, "Failed to delete vnf from workflow relation"); + } + + return new ResponseEntity<>(vnfWorkflowRelationResponse, OK); + } + + private ResponseEntity handleException(Exception exception, String msg) { + LOGGER.error(msg, exception); + return new ResponseEntity<>(new VnfWorkflowRelationResponse(Collections.singletonList(msg)), HttpStatus.INTERNAL_SERVER_ERROR); + } + + + private ExceptionResponse handleException(Exception e) { + return ControllersUtils.handleException(e, LOGGER); + } + + @ExceptionHandler(Exception.class) + @ResponseStatus(value=OK) //return 200 for Backwards compatibility with the previous responses to scheduler + private MsoResponseWrapperInterface exceptionHandler(Exception e) { + return exceptionHandler(e, INTERNAL_SERVER_ERROR); + } + + @ExceptionHandler({ + javax.ws.rs.BadRequestException.class, + }) + @ResponseStatus(value = OK) //return 200 for Backwards compatibility with the previous responses to scheduler + public MsoResponseWrapperInterface clientDerivedExceptionAsBadRequest(Exception e) { + // same handler, different HTTP Code + return exceptionHandler(e, BAD_REQUEST); + } + + private MsoResponseWrapperInterface exceptionHandler(Exception e, HttpStatus httpStatus) { + LOGGER.error(EELFLoggerDelegate.errorLogger, "{}: {}", getMethodName(), ExceptionUtils.getMessage(e), e); + MsoResponseWrapper2 responseWrapper2 = new MsoResponseWrapper2<>(httpStatus.value(), new MsoExceptionResponse(e)); + return responseWrapper2; + } + +} diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/ControllersUtils.java b/vid-app-common/src/main/java/org/onap/vid/controller/ControllersUtils.java new file mode 100644 index 000000000..9be6ad51f --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/controller/ControllersUtils.java @@ -0,0 +1,45 @@ +package org.onap.vid.controller; + +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.onap.portalsdk.core.domain.User; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.portalsdk.core.util.SystemProperties; +import org.onap.vid.model.ExceptionResponse; +import org.springframework.http.ResponseEntity; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import javax.ws.rs.WebApplicationException; + +import static org.onap.vid.utils.Logging.getMethodCallerName; + +public class ControllersUtils { + + + public static String extractUserId(HttpServletRequest request) { + String userId = ""; + HttpSession session = request.getSession(); + if (session != null) { + User user = (User) session.getAttribute(SystemProperties.getProperty(SystemProperties.USER_ATTRIBUTE_NAME)); + if (user != null) { + //userId = user.getHrid(); + userId = user.getLoginId(); + if (userId == null) + userId = user.getOrgUserId(); + } + } + return userId; + } + + public static ExceptionResponse handleException(Exception e, EELFLoggerDelegate logger) { + logger.error(EELFLoggerDelegate.errorLogger, "{}: {}", getMethodCallerName(), ExceptionUtils.getMessage(e), e); + + ExceptionResponse exceptionResponse = new ExceptionResponse(e); + return exceptionResponse; + } + + public static ResponseEntity handleWebApplicationException(WebApplicationException e, EELFLoggerDelegate logger) { + return ResponseEntity.status(e.getResponse().getStatus()).body(ControllersUtils.handleException(e, logger)); + } + +} diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/FeatureTogglingController.java b/vid-app-common/src/main/java/org/onap/vid/controller/FeatureTogglingController.java new file mode 100644 index 000000000..a90e71d48 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/controller/FeatureTogglingController.java @@ -0,0 +1,29 @@ +package org.onap.vid.controller; + +import org.onap.portalsdk.core.controller.RestrictedBaseController; +import org.onap.vid.properties.Features; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +import java.util.HashMap; +import java.util.Map; + +@RestController +@RequestMapping("flags") +public class FeatureTogglingController extends RestrictedBaseController { + + @RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + public @ResponseBody Map getFeatureToggles() + { + HashMap flags = new HashMap <>(); + for(Features flag : Features.values()){ + flags.put(flag.name(), flag.isActive()); + } + return flags; + + + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/HealthCheckController.java b/vid-app-common/src/main/java/org/onap/vid/controller/HealthCheckController.java new file mode 100644 index 000000000..2c42da279 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/controller/HealthCheckController.java @@ -0,0 +1,135 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.vid.controller; + +import org.onap.portalsdk.core.controller.UnRestrictedBaseController; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.portalsdk.core.util.SystemProperties; +import org.onap.vid.dao.FnAppDoaImpl; +import org.onap.vid.model.GitRepositoryState; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import java.io.IOException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Properties; + +import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; +import static org.springframework.http.HttpStatus.OK; + +/** + * Controller for user profile view. The view is restricted to authenticated + * users. The view name resolves to page user_profile.jsp which uses Angular. + */ + +@RestController +@RequestMapping("/") +public class HealthCheckController extends UnRestrictedBaseController { + + private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(HealthCheckController.class); + private static final DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss:SSSS"); + private static final String GIT_PROPERTIES_FILENAME = "git.properties"; + private FnAppDoaImpl fnAppDoaImpl; + + @Autowired + public HealthCheckController(FnAppDoaImpl fnAppDoaImpl) { + this.fnAppDoaImpl = fnAppDoaImpl; + } + + /** + * Obtain the HealthCheck Status from the System.Properties file. + * Used by IDNS for redundancy + * + * @return ResponseEntity The response entity + */ + @RequestMapping(value = "/healthCheck", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + public HealthStatus getHealthCheckStatusForIDNS() { + return createCorrespondingStatus(); + } + + /** + * Obtain the HealthCheck Status from the System.Properties file. + * + * @return ResponseEntity The response entity + */ + @RequestMapping(value = "rest/healthCheck/{User-Agent}/{X-ECOMP-RequestID}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + public HealthStatus getHealthCheck( + @PathVariable("User-Agent") String UserAgent, + @PathVariable("X-ECOMP-RequestID") String ECOMPRequestID) { + LOGGER.debug(EELFLoggerDelegate.debugLogger, "User-Agent ", UserAgent); + LOGGER.debug(EELFLoggerDelegate.debugLogger, "X-ECOMP-RequestID ", ECOMPRequestID); + return createCorrespondingStatus(); + } + + @RequestMapping(value = "/commitInfo", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + public GitRepositoryState getCommitInfo() throws IOException { + Properties properties = new Properties(); + properties.load(getClass().getClassLoader().getResourceAsStream(GIT_PROPERTIES_FILENAME)); + return new GitRepositoryState(properties); + } + + private HealthStatus createCorrespondingStatus() { + logData(); + try { + int count = fnAppDoaImpl.getProfileCount(getUrl(), getUsername(), getPassword()); + LOGGER.debug(EELFLoggerDelegate.debugLogger, "count:::", count); + return okStatus(); + } catch (Exception ex) { + String errorMsg = ex.getMessage(); + LOGGER.error(EELFLoggerDelegate.errorLogger, errorMsg); + return errorStatus(errorMsg); + } + } + + private void logData() { + LOGGER.debug(EELFLoggerDelegate.debugLogger, "Performing health check"); + LOGGER.debug(EELFLoggerDelegate.debugLogger, "URL::", getUrl()); + LOGGER.debug(EELFLoggerDelegate.debugLogger, "username::", getUsername()); + } + + private HealthStatus okStatus() { + return new HealthStatus(OK, dateFormat.format(new Date()), "health check succeeded"); + } + + private HealthStatus errorStatus(String msg) { + return new HealthStatus(INTERNAL_SERVER_ERROR, dateFormat.format( + new Date()), "health check failed: " + msg); + } + + private String getUrl() { + return SystemProperties.getProperty("db.connectionURL"); + } + + private String getUsername() { + return SystemProperties.getProperty("db.userName"); + } + + private String getPassword() { + return SystemProperties.getProperty("db.password"); + } +} + diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/HealthStatus.java b/vid-app-common/src/main/java/org/onap/vid/controller/HealthStatus.java new file mode 100644 index 000000000..14372b5de --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/controller/HealthStatus.java @@ -0,0 +1,31 @@ +package org.onap.vid.controller; + +import org.springframework.http.HttpStatus; + +/** + * Model for JSON response with health-check results. + */ +public final class HealthStatus { + + private final int statusCode; + private final String detailedMsg; + private final String date; + + public HealthStatus(HttpStatus code, String date, String detailedMsg) { + this.statusCode = code.value(); + this.detailedMsg = detailedMsg; + this.date = date; + } + + public int getStatusCode() { + return statusCode; + } + + public String getDetailedMsg() { + return detailedMsg; + } + + public String getDate() { + return date; + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/LoggerController.java b/vid-app-common/src/main/java/org/onap/vid/controller/LoggerController.java new file mode 100644 index 000000000..698ea5469 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/controller/LoggerController.java @@ -0,0 +1,115 @@ +package org.onap.vid.controller; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.FileAppender; +import ch.qos.logback.core.spi.AppenderAttachable; +import org.apache.commons.io.input.ReversedLinesFileReader; +import org.apache.commons.lang3.StringUtils; +import org.onap.portalsdk.core.controller.RestrictedBaseController; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.vid.model.ExceptionResponse; +import org.onap.vid.roles.Role; +import org.onap.vid.roles.RoleProvider; +import org.onap.vid.utils.Streams; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.InternalServerErrorException; +import javax.ws.rs.NotAuthorizedException; +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Objects; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static com.att.eelf.configuration.Configuration.GENERAL_LOGGER_NAME; + + +@RestController +@RequestMapping("logger") +public class LoggerController extends RestrictedBaseController { + + private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(LoggerController.class); + + @Autowired + RoleProvider roleProvider; + + @RequestMapping(value = "/{loggerName:audit|error|metrics}", method = RequestMethod.GET) + public String getLog(@PathVariable String loggerName, HttpServletRequest request, + @RequestParam(value="limit", defaultValue = "5000") Integer limit) throws IOException { + + List roles = roleProvider.getUserRoles(request); + boolean userPermitted = roleProvider.userPermissionIsReadLogs(roles); + if (!userPermitted) { + throw new NotAuthorizedException("User not authorized to get logs"); + } + + String logfilePath = getLogfilePath(loggerName); + + try (final ReversedLinesFileReader reader = new ReversedLinesFileReader(new File(logfilePath))) { + Supplier reverseLinesSupplier = () -> { + try { + return reader.readLine(); + } catch (NullPointerException e) { + // EOF Reached + return null; + } catch (IOException e) { + throw new InternalServerErrorException("error while reading " + logfilePath, e); + } + }; + + return Streams.takeWhile( + Stream.generate(reverseLinesSupplier), + line -> !StringUtils.contains(line, "Logging is started")) + .limit(limit) + .limit(5_000) + .filter(Objects::nonNull) + .collect(Collectors.joining("\n")); + } + } + + private String getLogfilePath(String loggerName) { + /* + Find the requested logger, and pull all of it's appenders. + Find the first of the appenders that is a FileAppender, and return it's + write-out filename. + */ + LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); + return context.getLoggerList().stream() + .filter(logger -> logger.getName().equals(GENERAL_LOGGER_NAME + "." + loggerName)) + .flatMap(this::pullSubAppenders) + .flatMap(appender -> { + // Appender might be "attachable", if so - roll-up its sub-appenders + return (appender instanceof AppenderAttachable) ? + pullSubAppenders((AppenderAttachable) appender) : Stream.of(appender); + }) + .filter(appender -> appender instanceof FileAppender) + .map(appender -> (FileAppender) appender) + .map(FileAppender::getFile) + .findFirst() + .orElseThrow(() -> new InternalServerErrorException("logfile for " + loggerName + " not found")); + } + + private Stream> pullSubAppenders(AppenderAttachable logger) { + return Streams.fromIterator(logger.iteratorForAppenders()); + } + + @ExceptionHandler({ NotAuthorizedException.class }) + @ResponseStatus(HttpStatus.UNAUTHORIZED) + public String notAuthorizedHandler(NotAuthorizedException e) { + return "UNAUTHORIZED"; + } + + @ExceptionHandler({ IOException.class, InternalServerErrorException.class }) + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + public ExceptionResponse ioExceptionHandler(Exception e) { + return ControllersUtils.handleException(e, LOGGER); + } + +} diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/MaintenanceController.java b/vid-app-common/src/main/java/org/onap/vid/controller/MaintenanceController.java new file mode 100644 index 000000000..40b7834d4 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/controller/MaintenanceController.java @@ -0,0 +1,152 @@ +package org.onap.vid.controller; + +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright © 2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Modifications Copyright 2018 Nokia + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +import org.onap.portalsdk.core.controller.UnRestrictedBaseController; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.vid.category.AddCategoryOptionResponse; +import org.onap.vid.category.AddCategoryOptionsRequest; +import org.onap.vid.category.CategoryParameterOptionRep; +import org.onap.vid.category.CategoryParametersResponse; +import org.onap.vid.model.CategoryParameter.Family; +import org.onap.vid.model.CategoryParameterOption; +import org.onap.vid.services.CategoryParameterService; +import org.onap.vid.services.CategoryParameterServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import javax.ws.rs.ForbiddenException; + +import static org.onap.vid.utils.Logging.getMethodCallerName; + +/** + * Controler for APIs that are used only by vid operators + */ + +@RestController +@RequestMapping("maintenance") +public class MaintenanceController extends UnRestrictedBaseController { + + private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(MaintenanceController.class); + private CategoryParameterService categoryParameterService; + + @Autowired + public MaintenanceController(CategoryParameterService categoryParameterService) { + this.categoryParameterService = categoryParameterService; + } + + /** + * Add list of options to one category parameter + */ + @RequestMapping(value = "/category_parameter/{categoryName}", method = RequestMethod.POST) + public ResponseEntity addCategoryOptions(@PathVariable String categoryName, + @RequestBody AddCategoryOptionsRequest option) { + debugStartLog(); + try { + AddCategoryOptionResponse response = categoryParameterService + .createCategoryParameterOptions(categoryName, option); + HttpStatus httpStatus = response.getErrors().isEmpty() ? HttpStatus.OK : HttpStatus.MULTI_STATUS; + debugEndLog(response); + return createResponseWithBody(httpStatus, response); + } catch (CategoryParameterServiceImpl.UnfoundedCategoryException exception) { + return createResponseWithBody(HttpStatus.NOT_FOUND, new AddCategoryOptionResponse(exception.getMessage())); + } catch (RuntimeException exception) { + LOGGER.error("failed to add option to parameter category " + categoryName, exception); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); + } + } + + @RequestMapping(value = "/category_parameter/{categoryName}", method = RequestMethod.PUT) + public ResponseEntity updateNameForOption(@PathVariable String categoryName, + @RequestBody CategoryParameterOptionRep option) { + debugStartLog(); + try { + AddCategoryOptionResponse response = categoryParameterService + .updateCategoryParameterOption(categoryName, option); + HttpStatus httpStatus = response.getErrors().isEmpty() ? HttpStatus.OK : HttpStatus.MULTI_STATUS; + debugEndLog(response); + return createResponseWithBody(httpStatus, response); + } catch (ForbiddenException exception) { + return createResponseWithBody(HttpStatus.FORBIDDEN, new AddCategoryOptionResponse(exception.getMessage())); + } catch (CategoryParameterServiceImpl.UnfoundedCategoryException | CategoryParameterServiceImpl.UnfoundedCategoryOptionException exception) { + return createResponseWithBody(HttpStatus.NOT_FOUND, new AddCategoryOptionResponse(exception.getMessage())); + + } catch (CategoryParameterServiceImpl.AlreadyExistOptionNameException exception) { + return createResponseWithBody(HttpStatus.CONFLICT, new AddCategoryOptionResponse(exception.getMessage())); + + } catch (RuntimeException exception) { + LOGGER.error("failed to update option to parameter category " + categoryName, exception); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); + } + } + + /** + * Gets the owning entity properties. + */ + @RequestMapping(value = "/category_parameter", method = RequestMethod.GET) + public ResponseEntity getCategoryParameter(@RequestParam(value = "familyName", required = true) Family familyName) { + debugStartLog(); + try { + CategoryParametersResponse response = categoryParameterService.getCategoryParameters(familyName); + debugEndLog(response); + return ResponseEntity.ok().body(response); + } catch (RuntimeException exception) { + LOGGER.error("failed to retrieve category parameter list from DB.", exception); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); + } + } + + /** + * Delete option of the category. + */ + @RequestMapping(value = "/delete_category_parameter/{categoryName}", method = RequestMethod.DELETE) + public ResponseEntity deleteCategoryOption(@PathVariable String categoryName, + @RequestBody CategoryParameterOption option) { + debugStartLog(); + + try { + categoryParameterService.deleteCategoryOption(categoryName, option); + debugEndLog(HttpStatus.OK); + return ResponseEntity.status(HttpStatus.OK).build(); + } catch (CategoryParameterServiceImpl.UnfoundedCategoryException exception) { + return createResponseWithBody(HttpStatus.NOT_FOUND, new AddCategoryOptionResponse(exception.getMessage())); + } catch (RuntimeException exception) { + LOGGER.error("failed to add/update owning entity option", exception); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); + } + } + + private ResponseEntity createResponseWithBody(HttpStatus status, AddCategoryOptionResponse response) { + return ResponseEntity.status(status).body(response); + } + + private void debugStartLog() { + LOGGER.debug(EELFLoggerDelegate.debugLogger, "start {}({})", getMethodCallerName()); + } + + private void debugEndLog(Object response) { + LOGGER.debug(EELFLoggerDelegate.debugLogger, "end {}() => {}", getMethodCallerName(), response); + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/MsoConfig.java b/vid-app-common/src/main/java/org/onap/vid/controller/MsoConfig.java new file mode 100644 index 000000000..7f90d6a43 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/controller/MsoConfig.java @@ -0,0 +1,66 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.vid.controller; + +import io.joshworks.restclient.http.mapper.ObjectMapper; +import org.onap.portalsdk.core.util.SystemProperties; +import org.onap.vid.aai.AaiClientInterface; +import org.onap.vid.client.SyncRestClient; +import org.onap.vid.factories.MsoRequestFactory; +import org.onap.vid.mso.MsoBusinessLogic; +import org.onap.vid.mso.MsoBusinessLogicImpl; +import org.onap.vid.mso.MsoInterface; +import org.onap.vid.mso.MsoProperties; +import org.onap.vid.mso.rest.MsoRestClientNew; +import org.onap.vid.services.CloudOwnerService; +import org.onap.vid.services.CloudOwnerServiceImpl; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.togglz.core.manager.FeatureManager; + + +@Configuration +public class MsoConfig { + + @Bean + public MsoRequestFactory createRequestDetailsFactory(){ + return new MsoRequestFactory(); + } + + @Bean + public MsoRestClientNew msoClient(ObjectMapper unirestObjectMapper){ + // Satisfy both interfaces -- MsoInterface and RestMsoImplementation + return new MsoRestClientNew(new SyncRestClient(unirestObjectMapper), SystemProperties.getProperty( + MsoProperties.MSO_SERVER_URL)); + } + + @Bean + public MsoBusinessLogic getMsoBusinessLogic(MsoInterface msoClient, FeatureManager featureManager){ + return new MsoBusinessLogicImpl(msoClient, featureManager); + } + + @Bean + public CloudOwnerService cloudOwnerService(AaiClientInterface aaiClient, FeatureManager featureManager) { + return new CloudOwnerServiceImpl(aaiClient, featureManager); + } + + +} diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/MsoController.java b/vid-app-common/src/main/java/org/onap/vid/controller/MsoController.java new file mode 100644 index 000000000..716267afa --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/controller/MsoController.java @@ -0,0 +1,705 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.vid.controller; + + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.onap.portalsdk.core.controller.RestrictedBaseController; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.vid.model.ExceptionResponse; +import org.onap.vid.model.SoftDeleteRequest; +import org.onap.vid.mso.MsoBusinessLogic; +import org.onap.vid.mso.MsoResponseWrapper; +import org.onap.vid.mso.MsoResponseWrapper2; +import org.onap.vid.mso.rest.Request; +import org.onap.vid.mso.rest.RequestDetails; +import org.onap.vid.mso.rest.RequestDetailsWrapper; +import org.onap.vid.mso.rest.Task; +import org.onap.vid.services.CloudOwnerService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.LinkedHashMap; +import java.util.List; + +import static org.onap.vid.utils.Logging.getMethodName; + +/** + * The Class MsoController. + */ +@RestController +@RequestMapping("mso") +public class MsoController extends RestrictedBaseController { + + /** + * The logger. + */ + private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(MsoController.class); + + /** + * The Constant SVC_INSTANCE_ID. + */ + public static final String SVC_INSTANCE_ID = ""; + public static final String REQUEST_TYPE = ""; + + /** + * The Constant CONFIGURATION_ID + */ + public static final String CONFIGURATION_ID = ""; + + /** + * The Constant VNF_INSTANCE_ID. + */ + public static final String VNF_INSTANCE_ID = ""; + public static final String START_LOG = " start"; + + private final MsoBusinessLogic msoBusinessLogic; + private final CloudOwnerService cloudOwnerService; + + @Autowired + public MsoController(MsoBusinessLogic msoBusinessLogic, CloudOwnerService cloudOwnerService) { + this.msoBusinessLogic = msoBusinessLogic; + this.cloudOwnerService = cloudOwnerService; + } + + /** + * Creates the svc instance. + * + * @param request the request + * @return the response entity + * @throws Exception the exception + */ + @RequestMapping(value = "/mso_create_svc_instance", method = RequestMethod.POST) + public ResponseEntity createSvcInstance(HttpServletRequest request, @RequestBody RequestDetails msoRequest) { + String methodName = "createSvcInstance"; + + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + START_LOG); + + // always return OK, the MSO status code is embedded in the body + + cloudOwnerService.enrichRequestWithCloudOwner(msoRequest); + MsoResponseWrapper w = msoBusinessLogic.createSvcInstance(msoRequest); + + return (new ResponseEntity<>(w.getResponse(), HttpStatus.OK)); + + } + + /** + * Creates the e2e svc instance. + * + * @param request the request + * @return the response entity + * @throws Exception the exception + */ + @RequestMapping(value = "/mso_create_e2e_svc_instance", method = RequestMethod.POST) + public ResponseEntity createE2eSvcInstance(HttpServletRequest request, @RequestBody LinkedHashMap msoRequest) { + String methodName = "createE2eSvcInstance"; + + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + START_LOG); + + // always return OK, the MSO status code is embedded in the body + + //cloudOwnerService.enrichRequestWithCloudOwner(msoRequest); + MsoResponseWrapper w = msoBusinessLogic.createE2eSvcInstance(msoRequest.get("requestDetails")); + + return (new ResponseEntity<>(w.getResponse(), HttpStatus.OK)); + + } + + /** + * Creates the vnf. + * + * @param serviceInstanceId the service instance id + * @param request the request + * @return the response entity + * @throws Exception the exception + */ + @RequestMapping(value = "/mso_create_vnf_instance/{serviceInstanceId}", method = RequestMethod.POST) + public ResponseEntity createVnf(@PathVariable("serviceInstanceId") String serviceInstanceId, HttpServletRequest request, @RequestBody RequestDetails msoRequest) { + + cloudOwnerService.enrichRequestWithCloudOwner(msoRequest); + MsoResponseWrapper w = msoBusinessLogic.createVnf(msoRequest, serviceInstanceId); + + // always return OK, the MSO status code is embedded in the body + + return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); + + } + + /** + * Creates the nw instance. + * + * @param serviceInstanceId the service instance id + * @param request the request + * @return the response entity + * @throws Exception the exception + */ + @RequestMapping(value = "/mso_create_nw_instance/{serviceInstanceId}", method = RequestMethod.POST) + public ResponseEntity createNwInstance(@PathVariable("serviceInstanceId") String serviceInstanceId, HttpServletRequest request, @RequestBody RequestDetails msoRequest) { + String methodName = "createNwInstance"; + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + " start, serviceInstanceId = " + serviceInstanceId); + + cloudOwnerService.enrichRequestWithCloudOwner(msoRequest); + MsoResponseWrapper w = msoBusinessLogic.createNwInstance(msoRequest, serviceInstanceId); + + return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); + + } + + /** + * Creates the volume group instance. + * + * @param serviceInstanceId the service instance id + * @param vnfInstanceId the vnf instance id + * @param request the request + * @return the response entity + * @throws Exception the exception + */ + @RequestMapping(value = "/mso_create_volumegroup_instance/{serviceInstanceId}/vnfs/{vnfInstanceId}", method = RequestMethod.POST) + public ResponseEntity createVolumeGroupInstance(@PathVariable("serviceInstanceId") String serviceInstanceId, @PathVariable("vnfInstanceId") String vnfInstanceId, + HttpServletRequest request, @RequestBody RequestDetails msoRequest) { + String methodName = "createVolumeGroupInstance"; + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + START_LOG); + + cloudOwnerService.enrichRequestWithCloudOwner(msoRequest); + MsoResponseWrapper w = msoBusinessLogic.createVolumeGroupInstance(msoRequest, serviceInstanceId, vnfInstanceId); + + // always return OK, the MSO status code is embedded in the body + return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); + } + + /** + * Creates the vf module instance. + * + * @param serviceInstanceId the service instance id + * @param vnfInstanceId the vnf instance id + * @param request the request + * @return the response entity + * @throws Exception the exception + */ + @RequestMapping(value = "/mso_create_vfmodule_instance/{serviceInstanceId}/vnfs/{vnfInstanceId}", method = RequestMethod.POST) + public ResponseEntity createVfModuleInstance(@PathVariable("serviceInstanceId") String serviceInstanceId, + @PathVariable("vnfInstanceId") String vnfInstanceId, HttpServletRequest request, @RequestBody RequestDetails msoRequest) { + String methodName = "createVfModuleInstance"; + + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + START_LOG); + + cloudOwnerService.enrichRequestWithCloudOwner(msoRequest); + MsoResponseWrapper w = msoBusinessLogic.createVfModuleInstance(msoRequest, serviceInstanceId, vnfInstanceId); + + // always return OK, the MSO status code is embedded in the body + + return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); + } + + /** + * Creates a configuration instance. + * + * @param serviceInstanceId the service instance id + * @param request the request + * @return the response entity + * @throws Exception the exception + */ + @RequestMapping(value = "/mso_create_configuration_instance/{serviceInstanceId}/configurations/", method = RequestMethod.POST) + public ResponseEntity createConfigurationInstance(@PathVariable("serviceInstanceId") String serviceInstanceId, + HttpServletRequest request, @RequestBody RequestDetailsWrapper msoRequest) { + String methodName = "createConfigurationInstance"; + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + START_LOG); + + cloudOwnerService.enrichRequestWithCloudOwner(msoRequest.getRequestDetails()); + MsoResponseWrapper w = msoBusinessLogic.createConfigurationInstance(msoRequest, serviceInstanceId); + + // always return OK, the MSO status code is embedded in the body + + return (new ResponseEntity<>(w.getResponse(), HttpStatus.OK)); + } + + /** + * Delete E2e svc instance. + * + * @param serviceInstanceId the service instance id + * @param request the request + * @return the response entity + * @throws Exception the exception + */ + @RequestMapping(value = "/mso_delete_e2e_svc_instance/{serviceInstanceId}", method = RequestMethod.POST) + public ResponseEntity deleteE2eSvcInstance(@PathVariable("serviceInstanceId") String serviceInstanceId, + HttpServletRequest request, @RequestBody LinkedHashMap msoRequest) { + + LOGGER.debug(EELFLoggerDelegate.debugLogger, "start {}({})", getMethodName(), msoRequest); + MsoResponseWrapper w = msoBusinessLogic.deleteE2eSvcInstance(msoRequest.get("requestDetails"), serviceInstanceId); + // always return OK, the MSO status code is embedded in the body + + return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); + + } + + /** + * Delete svc instance. + * + * @param serviceInstanceId the service instance id + * @param request the request + * @return the response entity + * @throws Exception the exception + */ + + @RequestMapping(value = "/mso_delete_svc_instance/{serviceInstanceId}", method = RequestMethod.POST) + public String deleteSvcInstance(@PathVariable("serviceInstanceId") String serviceInstanceId, + HttpServletRequest request, @RequestBody RequestDetails msoRequest, + @RequestParam(value = "serviceStatus") String serviceStatus) { + + LOGGER.debug(EELFLoggerDelegate.debugLogger, "start {}({})", getMethodName(), msoRequest); + MsoResponseWrapper w = msoBusinessLogic.deleteSvcInstance(msoRequest, serviceInstanceId, serviceStatus); + // always return OK, the MSO status code is embedded in the body + + return w.getResponse(); + } + + /** + * Delete vnf. + * + * @param serviceInstanceId the service instance id + * @param vnfInstanceId the vnf instance id + * @param request the request + * @return the response entity + * @throws Exception the exception + */ + @RequestMapping(value = "/mso_delete_vnf_instance/{serviceInstanceId}/vnfs/{vnfInstanceId}", method = RequestMethod.POST) + + public ResponseEntity deleteVnf(@PathVariable("serviceInstanceId") String serviceInstanceId, @PathVariable("vnfInstanceId") String vnfInstanceId, + HttpServletRequest request, @RequestBody RequestDetails msoRequest) { + String methodName = "deleteVnf"; + + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + START_LOG); + cloudOwnerService.enrichRequestWithCloudOwner(msoRequest); + MsoResponseWrapper w = msoBusinessLogic.deleteVnf(msoRequest, serviceInstanceId, vnfInstanceId); + + // always return OK, the MSO status code is embedded in the body + return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); + + } + + /** + * Delete configuration instance + * @param serviceInstanceId the service instance id + * @param configurationId the configuration id + * @param msoRequest the request + * @return the response entity + * @throws Exception the exception + */ + @RequestMapping(value = "mso_delete_configuration/{serviceInstanceId}/configurations/{configurationId}", + method = RequestMethod.POST) + public ResponseEntity deleteConfiguration( + @PathVariable("serviceInstanceId") String serviceInstanceId, + @PathVariable ("configurationId") String configurationId, + @RequestBody RequestDetailsWrapper msoRequest) { + + String methodName = "deleteConfiguration"; + LOGGER.debug(EELFLoggerDelegate.debugLogger, + "<== " + methodName + START_LOG); + + cloudOwnerService.enrichRequestWithCloudOwner(msoRequest.getRequestDetails()); + MsoResponseWrapper w = msoBusinessLogic.deleteConfiguration(msoRequest, serviceInstanceId, configurationId); + + // always return OK, the MSO status code is embedded in the body + return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); + } + + /** + * Activate configuration instance + * @param serviceInstanceId the service instace id + * @param configurationId the configuration id + * @param msoRequest the request + * @return the response entity + * @throws Exception the exception + */ + @RequestMapping(value = "mso_activate_configuration/{serviceInstanceId}/configurations/{configurationId}", + method = RequestMethod.POST) + public ResponseEntity activateConfiguration( + @PathVariable("serviceInstanceId") String serviceInstanceId, + @PathVariable("configurationId") String configurationId, + @RequestBody RequestDetails msoRequest) { + + cloudOwnerService.enrichRequestWithCloudOwner(msoRequest); + MsoResponseWrapper w = msoBusinessLogic.setConfigurationActiveStatus(msoRequest, serviceInstanceId, configurationId, true); + + // always return OK, the MSO status code is embedded in the body + return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); + } + + /** + * Deactivate configuration instance + * @param serviceInstanceId the service instace id + * @param configurationId the configuration id + * @param msoRequest the request + * @return the response entity + * @throws Exception the exception + */ + @RequestMapping(value = "mso_deactivate_configuration/{serviceInstanceId}/configurations/{configurationId}", + method = RequestMethod.POST) + public ResponseEntity deactivateConfiguration( + @PathVariable("serviceInstanceId") String serviceInstanceId, + @PathVariable("configurationId") String configurationId, + @RequestBody RequestDetails msoRequest) { + + cloudOwnerService.enrichRequestWithCloudOwner(msoRequest); + MsoResponseWrapper w = msoBusinessLogic.setConfigurationActiveStatus(msoRequest, serviceInstanceId, configurationId, false); + + // always return OK, the MSO status code is embedded in the body + return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); + } + + /** + * Disable port on configuration instance + * @param serviceInstanceId the service instance id + * @param configurationId the configuration instance id + * @param msoRequest the request + * @return the response entity + * @throws Exception the exception + */ + @RequestMapping(value = "mso_disable_port_configuration/{serviceInstanceId}/configurations/{configurationId}", + method = RequestMethod.POST) + public ResponseEntity disablePortOnConfiguration( + @PathVariable("serviceInstanceId") String serviceInstanceId, + @PathVariable("configurationId") String configurationId, + @RequestBody RequestDetails msoRequest) { + + cloudOwnerService.enrichRequestWithCloudOwner(msoRequest); + MsoResponseWrapper w = msoBusinessLogic.setPortOnConfigurationStatus(msoRequest, serviceInstanceId, configurationId, false); + + // always return OK, the MSO status code is embedded in the body + return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); + } + + /** + * Enable port on configuration instance + * @param serviceInstanceId the service instance id + * @param configurationId the configuration instance id + * @param msoRequest the request + * @return the response entity + * @throws Exception the exception + */ + @RequestMapping(value = "mso_enable_port_configuration/{serviceInstanceId}/configurations/{configurationId}", + method = RequestMethod.POST) + public ResponseEntity enablePortOnConfiguration( + @PathVariable("serviceInstanceId") String serviceInstanceId, + @PathVariable("configurationId") String configurationId, + @RequestBody RequestDetails msoRequest) { + + cloudOwnerService.enrichRequestWithCloudOwner(msoRequest); + MsoResponseWrapper w = msoBusinessLogic.setPortOnConfigurationStatus(msoRequest, serviceInstanceId, configurationId, true); + + // always return OK, the MSO status code is embedded in the body + return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); + } + + /** + * Delete vf module. + * + * @param serviceInstanceId the service instance id + * @param vnfInstanceId the vnf instance id + * @param vfModuleId the vf module id + * @param request the request + * @return the response entity + * @throws Exception the exception + */ + //mso_delete_vf_module/bc305d54-75b4-431b-adb2-eb6b9e546014/vnfs/fe9000-0009-9999/vfmodules/abeeee-abeeee-abeeee + @RequestMapping(value = "/mso_delete_vfmodule_instance/{serviceInstanceId}/vnfs/{vnfInstanceId}/vfModules/{vfModuleId}", method = RequestMethod.POST) + public ResponseEntity deleteVfModule( + @PathVariable("serviceInstanceId") String serviceInstanceId, @PathVariable("vnfInstanceId") String vnfInstanceId, + @PathVariable("vfModuleId") String vfModuleId, HttpServletRequest request, @RequestBody RequestDetails msoRequest) { + + String methodName = "deleteVfModule"; + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + START_LOG); + + cloudOwnerService.enrichRequestWithCloudOwner(msoRequest); + MsoResponseWrapper w = msoBusinessLogic.deleteVfModule(msoRequest, serviceInstanceId, vnfInstanceId, vfModuleId); + + // always return OK, the MSO status code is embedded in the body + return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); + } + + /** + * Delete volume group instance. + * + * @param serviceInstanceId the service instance id + * @param vnfInstanceId the vnf instance id + * @param volumeGroupId the volume group id + * @param request the request + * @return the response entity + * @throws Exception the exception + */ + @RequestMapping(value = "/mso_delete_volumegroup_instance/{serviceInstanceId}/vnfs/{vnfInstanceId}/volumeGroups/{volumeGroupId}", method = RequestMethod.POST) + public ResponseEntity deleteVolumeGroupInstance( + @PathVariable("serviceInstanceId") String serviceInstanceId, @PathVariable("vnfInstanceId") String vnfInstanceId, @PathVariable("volumeGroupId") String volumeGroupId, + HttpServletRequest request, @RequestBody RequestDetails msoRequest) { + String methodName = "deleteVolumeGroupInstance"; + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + START_LOG); + + cloudOwnerService.enrichRequestWithCloudOwner(msoRequest); + MsoResponseWrapper w = msoBusinessLogic.deleteVolumeGroupInstance(msoRequest, serviceInstanceId, vnfInstanceId, volumeGroupId); + + // always return OK, the MSO status code is embedded in the body + return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); + } + + /** + * Delete nw instance. + * + * @param serviceInstanceId the service instance id + * @param networkInstanceId the network instance id + * @param request the request + * @return the response entity + * @throws Exception the exception + */ + @RequestMapping(value = "/mso_delete_nw_instance/{serviceInstanceId}/networks/{networkInstanceId}", method = RequestMethod.POST) + public ResponseEntity deleteNwInstance(@PathVariable("serviceInstanceId") String serviceInstanceId, + @PathVariable("networkInstanceId") String networkInstanceId, HttpServletRequest request, @RequestBody RequestDetails msoRequest) { + String methodName = "deleteNwInstance"; + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + START_LOG); + + cloudOwnerService.enrichRequestWithCloudOwner(msoRequest); + MsoResponseWrapper w = msoBusinessLogic.deleteNwInstance(msoRequest, serviceInstanceId, networkInstanceId); + + // always return OK, the MSO status code is embedded in the body + return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); + } + + /** + * Gets the orchestration request. + * + * @param requestId the request id + * @param request the request + * @return the orchestration request + * @throws Exception the exception + */ + @RequestMapping(value = "/mso_get_orch_req/{requestId}", method = RequestMethod.GET) + public ResponseEntity getOrchestrationRequest(@PathVariable("requestId") String requestId, + HttpServletRequest request) { + + String methodName = "getOrchestrationRequest"; + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + START_LOG); + + + MsoResponseWrapper w = msoBusinessLogic.getOrchestrationRequest(requestId); + + // always return OK, the MSO status code is embedded in the body + return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); + } + + /** + * Gets the orchestration requests. + * + * @param filterString the filter string + * @param request the request + * @return the orchestration requests + * @throws Exception the exception + */ + @RequestMapping(value = "/mso_get_orch_reqs/{filterString}", method = RequestMethod.GET) + public ResponseEntity getOrchestrationRequests(@PathVariable("filterString") String filterString, + HttpServletRequest request) { + + String methodName = "getOrchestrationRequests"; + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + START_LOG); + + + MsoResponseWrapper w = msoBusinessLogic.getOrchestrationRequests(filterString); + + // always return OK, the MSO status code is embedded in the body + return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); + } + + /** + * activate to a pnf instance. + * + * @param serviceInstanceId the id of the service. + * @param requestDetails the body of the request. + * @return the response entity + * @throws Exception the exception + */ + @RequestMapping(value = "/mso_activate_service_instance/{serviceInstanceId}", method = RequestMethod.POST) + public ResponseEntity activateServiceInstance(@PathVariable("serviceInstanceId") String serviceInstanceId, @RequestBody RequestDetails requestDetails) { + String methodName = "activateServiceInstance"; + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + START_LOG); + + MsoResponseWrapper w = msoBusinessLogic.setServiceInstanceStatus(requestDetails, serviceInstanceId, true); + return new ResponseEntity<>(w.getResponse(), HttpStatus.OK); + } + + /** + * deactivate a service instance. + * + * @param serviceInstanceId the id of the service. + * @param requestDetails the body of the request. + * @return the response entity + * @throws Exception the exception + */ + @RequestMapping(value = "/mso_deactivate_service_instance/{serviceInstanceId}", method = RequestMethod.POST) + public ResponseEntity deactivateServiceInstance(@PathVariable("serviceInstanceId") String serviceInstanceId, @RequestBody RequestDetails requestDetails) { + String methodName = "deactivateServiceInstance"; + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + START_LOG); + + MsoResponseWrapper w = msoBusinessLogic.setServiceInstanceStatus(requestDetails, serviceInstanceId, false); + return new ResponseEntity<>(w.getResponse(), HttpStatus.OK); + } + + /** + * Gets the orchestration requests for the dashboard. + * currently its all the orchestration requests with RequestType updateInstance or replaceInstance. + * @return the orchestration requests + * @throws Exception the exception + */ + @RequestMapping(value = "/mso_get_orch_reqs/dashboard", method = RequestMethod.GET) + public List getOrchestrationRequestsForDashboard() { + + String methodName = "getOrchestrationRequestsForDashboard"; + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + START_LOG); + + + return msoBusinessLogic.getOrchestrationRequestsForDashboard(); + } + + /** + * Gets the Manual Tasks for the given request id. + * + * @param originalRequestId the id of the original request. + * @return the tasks + * @throws Exception the exception + */ + @RequestMapping(value = "/mso_get_man_task/{originalRequestId}", method = RequestMethod.GET) + public List getManualTasksByRequestId(@PathVariable("originalRequestId") String originalRequestId) { + + String methodName = "getManualTasksByRequestId"; + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + START_LOG); + + return msoBusinessLogic.getManualTasksByRequestId(originalRequestId); + } + + /** + * Complete the manual task. + * + * @param taskId the id of the task to complete. + * @param requestDetails the body of the request. + * @return the response entity + * @throws Exception the exception + */ + @RequestMapping(value = "/mso_post_man_task/{taskId}", method = RequestMethod.POST) + public ResponseEntity manualTaskComplete(@PathVariable("taskId") String taskId , @RequestBody RequestDetails requestDetails) { + + String methodName = "manualTaskComplete"; + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + START_LOG); + + MsoResponseWrapper w = msoBusinessLogic.completeManualTask(requestDetails, taskId); + return new ResponseEntity<>(w.getResponse(), HttpStatus.OK); + } + + @RequestMapping(value = "/mso_remove_relationship/{serviceInstanceId}", method = RequestMethod.POST) + public ResponseEntity removeRelationshipFromServiceInstance(@PathVariable("serviceInstanceId") String serviceInstanceId , + @RequestBody RequestDetails requestDetails) { + + String methodName = "removeRelationshipFromServiceInstance"; + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + START_LOG); + + MsoResponseWrapper w; + try { + w = msoBusinessLogic.removeRelationshipFromServiceInstance(requestDetails, serviceInstanceId); + } catch (Exception e){ + LOGGER.error("Internal error when calling MSO controller logic for {}", methodName, e); + return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + return new ResponseEntity<>(w.getResponse(), HttpStatus.OK); + } + + @RequestMapping(value = "/mso_add_relationship/{serviceInstanceId}", method = RequestMethod.POST) + public ResponseEntity addRelationshipToServiceInstance(@PathVariable("serviceInstanceId") String serviceInstanceId , + @RequestBody RequestDetails requestDetails) { + + String methodName = "addRelationshipToServiceInstance"; + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + START_LOG); + + MsoResponseWrapper w; + try { + w = msoBusinessLogic.addRelationshipToServiceInstance(requestDetails, serviceInstanceId); + } catch (Exception e){ + LOGGER.error("Internal error when calling MSO controller logic for {}", methodName, e); + return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + return new ResponseEntity<>(w.getResponse(), HttpStatus.OK); + } + + @RequestMapping(value = "/mso_activate_fabric_configuration/{serviceInstanceId}", method = RequestMethod.POST) + public MsoResponseWrapper2 activateFabricConfiguration( + @PathVariable("serviceInstanceId") String serviceInstanceId , + @RequestBody RequestDetails requestDetails) { + + String methodName = "activateFabricConfiguration"; + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + START_LOG); + + return msoBusinessLogic.activateFabricConfiguration(serviceInstanceId, requestDetails); + } + + @RequestMapping(value = "/mso_vfmodule_soft_delete/{serviceInstanceId}/{vnfInstanceId}/{vfModuleInstanceId}", method = RequestMethod.POST) + public MsoResponseWrapper2 deactivateAndCloudDelete( + @PathVariable("serviceInstanceId") String serviceInstanceId, + @PathVariable("vnfInstanceId") String vnfInstanceId, + @PathVariable("vfModuleInstanceId") String vfModuleInstanceId, + @RequestBody SoftDeleteRequest softDeleteRequest) { + + String methodName = "deactivateAndCloudDelete"; + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + START_LOG); + + RequestDetails requestDetails = msoBusinessLogic.buildRequestDetailsForSoftDelete(softDeleteRequest); + + cloudOwnerService.enrichRequestWithCloudOwner(requestDetails); + return msoBusinessLogic.deactivateAndCloudDelete(serviceInstanceId, vnfInstanceId, vfModuleInstanceId, requestDetails); + } + + + /** + * Exception handler. + * + * @param e the e + * @param response the response + * @throws IOException Signals that an I/O exception has occurred. + */ + @ExceptionHandler(Exception.class) + private void exceptionHandler(Exception e, HttpServletResponse response) throws IOException { + + ControllersUtils.handleException(e, LOGGER); + + response.setContentType("application/json; charset=UTF-8"); + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + + ExceptionResponse exceptionResponse = new ExceptionResponse(); + exceptionResponse.setException(e.getClass().toString().replaceFirst("^.*\\.", "")); + exceptionResponse.setMessage(e.getMessage()); + + response.getWriter().write(new ObjectMapper().writeValueAsString(exceptionResponse)); + + response.flushBuffer(); + + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/OperationalEnvironmentController.java b/vid-app-common/src/main/java/org/onap/vid/controller/OperationalEnvironmentController.java new file mode 100644 index 000000000..21aef6858 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/controller/OperationalEnvironmentController.java @@ -0,0 +1,362 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.vid.controller; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.base.MoreObjects; +import io.joshworks.restclient.http.HttpResponse; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.vid.changeManagement.RequestDetailsWrapper; +import org.onap.vid.model.ExceptionResponse; +import org.onap.vid.model.RequestReferencesContainer; +import org.onap.vid.mso.MsoBusinessLogic; +import org.onap.vid.mso.MsoInterface; +import org.onap.vid.mso.MsoResponseWrapper2; +import org.onap.vid.mso.model.OperationalEnvironmentActivateInfo; +import org.onap.vid.mso.model.OperationalEnvironmentDeactivateInfo; +import org.onap.vid.mso.rest.OperationalEnvironment.OperationEnvironmentRequestDetails; +import org.onap.vid.mso.rest.RequestDetails; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.MissingServletRequestParameterException; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.onap.vid.utils.Logging.getMethodCallerName; +import static org.onap.vid.utils.Logging.getMethodName; + +@RestController +@RequestMapping("operationalEnvironment") +public class OperationalEnvironmentController extends VidRestrictedBaseController { + + private final MsoInterface restMso; + private final MsoBusinessLogic msoBusinessLogic; + + private static final Pattern RECOVERY_ACTION_MESSAGE_PATTERN = Pattern.compile("from String \"(.*)\": value not"); + + + @Autowired + public OperationalEnvironmentController(MsoBusinessLogic msoBusinessLogic, MsoInterface msoClientInterface) { + this.restMso = msoClientInterface; + this.msoBusinessLogic = msoBusinessLogic; + } + + @RequestMapping(value = "/create", method = RequestMethod.POST) + public MsoResponseWrapper2 createOperationalEnvironment(HttpServletRequest request, @RequestBody OperationalEnvironmentCreateBody operationalEnvironment) { + debugStart(operationalEnvironment); + String userId = ControllersUtils.extractUserId(request); + RequestDetailsWrapper requestDetailsWrapper = msoBusinessLogic.convertParametersToRequestDetails(operationalEnvironment, userId); + String path = msoBusinessLogic.getOperationalEnvironmentCreationPath(); + + HttpResponse msoResponse = restMso.post(path, requestDetailsWrapper, RequestReferencesContainer.class); + debugEnd(msoResponse); + return new MsoResponseWrapper2<>(msoResponse); + } + + @RequestMapping(value = "/activate", method = RequestMethod.POST) + public MsoResponseWrapper2 activate(HttpServletRequest request, + @RequestParam("operationalEnvironment") String operationalEnvironmentId, + @RequestBody OperationalEnvironmentActivateBody activateRequest) throws MissingServletRequestParameterException { + + verifyIsNotEmpty(operationalEnvironmentId, "operationalEnvironment"); + + //manifest is null in case of wrong manifest structure (deserialization failure of the manifest) + if (activateRequest.getManifest()==null || activateRequest.getManifest().getServiceModelList()==null) { + throw new BadManifestException("Manifest structure is wrong"); + } + + String userId = ControllersUtils.extractUserId(request); + + OperationalEnvironmentActivateInfo activateInfo = new OperationalEnvironmentActivateInfo(activateRequest, userId, operationalEnvironmentId); + debugStart(activateInfo); + + String path = msoBusinessLogic.getOperationalEnvironmentActivationPath(activateInfo); + RequestDetailsWrapper requestDetailsWrapper = msoBusinessLogic.createOperationalEnvironmentActivationRequestDetails(activateInfo); + + HttpResponse msoResponse = restMso.post(path, requestDetailsWrapper, RequestReferencesContainer.class); + + debugEnd(msoResponse); + return new MsoResponseWrapper2<>(msoResponse); + } + + @RequestMapping(value = "/deactivate", method = RequestMethod.POST) + public MsoResponseWrapper2 deactivate(HttpServletRequest request, + @RequestParam("operationalEnvironment") String operationalEnvironmentId, + @RequestBody Map deactivationRequest) throws MissingServletRequestParameterException { + + verifyIsNotEmpty(operationalEnvironmentId, "operationalEnvironment"); + + String userId = ControllersUtils.extractUserId(request); + + OperationalEnvironmentDeactivateInfo deactivateInfo = new OperationalEnvironmentDeactivateInfo(userId, operationalEnvironmentId); + debugStart(deactivateInfo); + + String path = msoBusinessLogic.getOperationalEnvironmentDeactivationPath(deactivateInfo); + RequestDetailsWrapper requestDetailsWrapper = msoBusinessLogic.createOperationalEnvironmentDeactivationRequestDetails(deactivateInfo); + + HttpResponse msoResponse = restMso.post(path, requestDetailsWrapper, RequestReferencesContainer.class); + + debugEnd(msoResponse); + return new MsoResponseWrapper2<>(msoResponse); + } + + @RequestMapping(value = "/requestStatus", method = RequestMethod.GET) + public MsoResponseWrapper2 status(HttpServletRequest request, @RequestParam("requestId") String requestId) throws MissingServletRequestParameterException { + + debugStart(requestId); + + verifyIsNotEmpty(requestId, "requestId"); + String path = msoBusinessLogic.getCloudResourcesRequestsStatusPath(requestId); + + HttpResponse msoResponse = restMso.get(path, HashMap.class); + + LOGGER.debug(EELFLoggerDelegate.debugLogger, "end {}() => {}", getMethodName(), msoResponse); + return new MsoResponseWrapper2<>(msoResponse); + } + + @ExceptionHandler({ + org.springframework.web.bind.MissingServletRequestParameterException.class, + BadManifestException.class + }) + @ResponseStatus(value = HttpStatus.BAD_REQUEST) + public ExceptionResponse clientDerivedExceptionAsBadRequest(Exception e) { + // same handler, different HTTP Code + return exceptionHandler(e); + } + + @ExceptionHandler({ + org.springframework.http.converter.HttpMessageNotReadableException.class, + }) + @ResponseStatus(value = HttpStatus.BAD_REQUEST) + public ExceptionResponse handlingHttpMessageNotReadableException(Exception e) { + //in case of wrong value in manifest for RecoveryAction the message contains the class name. + //The wrong value is in also part of this messages + //within the pattern of: String value '': value not + //so we use regex to find the wrong value + if (e.getMessage().contains(OperationalEnvironmentRecoveryAction.class.getName())) { + LOGGER.error(EELFLoggerDelegate.errorLogger, "{}: {}", getMethodName(), ExceptionUtils.getMessage(e), e); + String message = "Wrong value for RecoveryAction in manifest. Allowed options are: "+OperationalEnvironmentRecoveryAction.options; + + Matcher matcher = RECOVERY_ACTION_MESSAGE_PATTERN.matcher(e.getMessage()); + if (matcher.find()) { + String wrongValue = matcher.group(1); + message = message+". Wrong value is: "+wrongValue; + } + return new ExceptionResponse(new BadManifestException(message)); + } + return exceptionHandler(e); + } + + + public enum OperationalEnvironmentRecoveryAction { + abort, + retry, + skip; + + public static final String options = Stream.of(OperationalEnvironmentRecoveryAction.values()).map(OperationalEnvironmentRecoveryAction::name).collect(Collectors.joining(", ")); + } + + public static class ActivateServiceModel { + private String serviceModelVersionId; + private OperationalEnvironmentRecoveryAction recoveryAction; + + public ActivateServiceModel() { + } + + public ActivateServiceModel(String serviceModelVersionId, OperationalEnvironmentRecoveryAction recoveryAction) { + this.serviceModelVersionId = serviceModelVersionId; + this.recoveryAction = recoveryAction; + } + + public String getServiceModelVersionId() { + return serviceModelVersionId; + } + + public void setServiceModelVersionId(String serviceModelVersionId) { + this.serviceModelVersionId = serviceModelVersionId; + } + + public OperationalEnvironmentRecoveryAction getRecoveryAction() { + return recoveryAction; + } + + public void setRecoveryAction(OperationalEnvironmentRecoveryAction recoveryAction) { + this.recoveryAction = recoveryAction; + } + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static class OperationalEnvironmentManifest { + + + private List serviceModelList; + + public OperationalEnvironmentManifest() { + } + + public OperationalEnvironmentManifest(List serviceModelList) { + this.serviceModelList = serviceModelList; + } + + public List getServiceModelList() { + return serviceModelList; + } + + public void setServiceModelList(List serviceModelList) { + this.serviceModelList = serviceModelList; + } + } + + public static class OperationalEnvironmentActivateBody { + private final String relatedInstanceId; + private final String relatedInstanceName; + private final String workloadContext; + private final OperationalEnvironmentManifest manifest; + + public OperationalEnvironmentActivateBody(@JsonProperty(value = "relatedInstanceId", required = true) String relatedInstanceId, + @JsonProperty(value = "relatedInstanceName", required = true) String relatedInstanceName, + @JsonProperty(value = "workloadContext", required = true) String workloadContext, + @JsonProperty(value = "manifest", required = true) OperationalEnvironmentManifest manifest) { + this.relatedInstanceId = relatedInstanceId; + this.relatedInstanceName = relatedInstanceName; + this.workloadContext = workloadContext; + this.manifest = manifest; + } + + + public String getRelatedInstanceId() { + return relatedInstanceId; + } + + public String getRelatedInstanceName() { + return relatedInstanceName; + } + + public String getWorkloadContext() { + return workloadContext; + } + + public OperationalEnvironmentManifest getManifest() { + return manifest; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("relatedInstanceId", relatedInstanceId) + .add("relatedInstanceName", relatedInstanceName) + .add("workloadContext", workloadContext) + .add("manifest", manifest) + .toString(); + } + } + + public static class OperationalEnvironmentCreateBody { + private final String instanceName; + private final String ecompInstanceId; + private final String ecompInstanceName; + private final String operationalEnvironmentType; + private final String tenantContext; + private final String workloadContext; + + public OperationalEnvironmentCreateBody(@JsonProperty(value = "instanceName", required = true) String instanceName, + @JsonProperty(value = "ecompInstanceId", required = true) String ecompInstanceId, + @JsonProperty(value = "ecompInstanceName", required = true) String ecompInstanceName, + @JsonProperty(value = "operationalEnvironmentType", required = true) String operationalEnvironmentType, + @JsonProperty(value = "tenantContext", required = true) String tenantContext, + @JsonProperty(value = "workloadContext", required = true) String workloadContext) { + this.instanceName = instanceName; + this.ecompInstanceId = ecompInstanceId; + this.ecompInstanceName = ecompInstanceName; + this.operationalEnvironmentType = operationalEnvironmentType; + this.tenantContext = tenantContext; + this.workloadContext = workloadContext; + } + + public String getInstanceName() { + return instanceName; + } + + public String getEcompInstanceId() { + return ecompInstanceId; + } + + public String getEcompInstanceName() { + return ecompInstanceName; + } + + public String getOperationalEnvironmentType() { + return operationalEnvironmentType; + } + + public String getTenantContext() { + return tenantContext; + } + + public String getWorkloadContext() { + return workloadContext; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("instanceName", instanceName) + .add("ecompInstanceId", ecompInstanceId) + .add("ecompInstanceName", ecompInstanceName) + .add("operationalEnvironmentType", operationalEnvironmentType) + .add("tenantContext", tenantContext) + .add("workloadContext", workloadContext) + .toString(); + } + } + + private void debugEnd(HttpResponse msoResponse) { + LOGGER.debug(EELFLoggerDelegate.debugLogger, "end {}() => {}", getMethodCallerName(), msoResponse); + } + + private void debugStart(Object requestInfo) { + LOGGER.debug(EELFLoggerDelegate.debugLogger, "start {}({})", getMethodCallerName(), requestInfo); + } + + private void verifyIsNotEmpty(String fieldValue, String fieldName) throws MissingServletRequestParameterException { + if (StringUtils.isEmpty(fieldValue)) { + throw new MissingServletRequestParameterException(fieldName, "String"); + } + } + + public static class BadManifestException extends RuntimeException { + public BadManifestException(String message) { + super(message); + } + } + +} diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/ProbeController.java b/vid-app-common/src/main/java/org/onap/vid/controller/ProbeController.java new file mode 100644 index 000000000..1324ebb12 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/controller/ProbeController.java @@ -0,0 +1,42 @@ +package org.onap.vid.controller; + +import org.onap.portalsdk.core.controller.RestrictedBaseController; +import org.onap.vid.aai.AaiClient; +import org.onap.vid.model.probes.ExternalComponentStatus; +import org.onap.vid.mso.MsoBusinessLogic; +import org.onap.vid.scheduler.SchedulerService; +import org.onap.vid.services.VidService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import java.util.ArrayList; +import java.util.List; + +@RestController +@RequestMapping("probe") +public class ProbeController extends RestrictedBaseController { + + private final AaiClient aaiClient; + private final VidService vidService; + private final MsoBusinessLogic msoBusinessLogic; + private final SchedulerService schedulerService; + + @Autowired + public ProbeController(AaiClient aaiClient, VidService vidService, MsoBusinessLogic msoBusinessLogic, SchedulerService schedulerService) { + this.aaiClient = aaiClient; + this.vidService = vidService; + this.msoBusinessLogic = msoBusinessLogic; + this.schedulerService = schedulerService; + } + + @RequestMapping(method= RequestMethod.GET) + public List getProbe() { + List componentStatuses = new ArrayList<>(); + componentStatuses.add(aaiClient.probeAaiGetAllSubscribers()); + componentStatuses.add(schedulerService.probeGetSchedulerChangeManagements()); + return componentStatuses; + } + +} diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/PropertyController.java b/vid-app-common/src/main/java/org/onap/vid/controller/PropertyController.java new file mode 100644 index 000000000..2f8d6e299 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/controller/PropertyController.java @@ -0,0 +1,126 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.vid.controller; + +import org.onap.portalsdk.core.controller.RestrictedBaseController; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.portalsdk.core.util.SystemProperties; +import org.onap.vid.category.CategoryParametersResponse; +import org.onap.vid.model.CategoryParameter.Family; +import org.onap.vid.services.CategoryParameterService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; + +import javax.servlet.http.HttpServletRequest; + +import static org.onap.vid.utils.Logging.getMethodName; + +/** + * The Class PropertyController. + */ +@RestController +public class PropertyController extends RestrictedBaseController{ + + + /** The logger. */ + private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(PropertyController.class); + + @Autowired + protected CategoryParameterService categoryParameterService; + + + /** + * Welcome. + * + * @param request the request + * @return the model and view + */ + @RequestMapping(value = {"/propertyhome" }, method = RequestMethod.GET) + public ModelAndView welcome(HttpServletRequest request) { + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== PropertyController welcome start"); + return new ModelAndView(getViewName()); + } + + /** + * Gets the property. + * + * @param name the name + * @param defaultvalue the defaultvalue + * @param request the request + * @return the property + * @throws Exception the exception + */ + @RequestMapping(value = "/get_property/{name}/{defaultvalue}", method = RequestMethod.GET) + public ResponseEntity getProperty (@PathVariable("name") String name, @PathVariable("defaultvalue") String defaultvalue, + HttpServletRequest request) { + + String methodName = "getProperty"; + ResponseEntity resp = null; + String pvalue = null; + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + " start"); + + try { + // convert "_" to "." in the property name + if (name == null || name.length() == 0 ) { + return ( new ResponseEntity (defaultvalue, HttpStatus.OK)); + } + // convert "_" to "." in the property name + String propertyName = name.replace('_', '.'); + pvalue = SystemProperties.getProperty(propertyName); + if ( ( pvalue == null ) || ( pvalue.length() == 0 ) ) { + pvalue = defaultvalue; + } + resp = new ResponseEntity<>(pvalue, HttpStatus.OK); + } + catch (Exception e) { + LOGGER.info(EELFLoggerDelegate.errorLogger, "<== " + "." + methodName + e.toString()); + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + "." + methodName + e.toString()); + throw e; + } + LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + " returning " + pvalue); + return ( resp ); + } + + /** + * Gets the owning entity properties. + * @param request the request + * @return the property + * @throws Exception the exception + */ + @RequestMapping(value = "/category_parameter", method = RequestMethod.GET) + public ResponseEntity getCategoryParameter(HttpServletRequest request, @RequestParam(value="familyName", required = true) Family familyName) { + LOGGER.debug(EELFLoggerDelegate.debugLogger, "start {}({})", getMethodName()); + try { + CategoryParametersResponse response = categoryParameterService.getCategoryParameters(familyName); + LOGGER.debug(EELFLoggerDelegate.debugLogger, "end {}() => {}", getMethodName(), response); + return new ResponseEntity<>(response, HttpStatus.OK); + } + catch (Exception exception) { + LOGGER.error("failed to retrieve category parameter list from DB.", exception); + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + +} diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/RoleGeneratorController.java b/vid-app-common/src/main/java/org/onap/vid/controller/RoleGeneratorController.java new file mode 100644 index 000000000..78f1e37d5 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/controller/RoleGeneratorController.java @@ -0,0 +1,26 @@ +package org.onap.vid.controller; + +import org.onap.portalsdk.core.controller.UnRestrictedBaseController; +import org.onap.vid.services.RoleGeneratorService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class RoleGeneratorController extends UnRestrictedBaseController { + @Autowired + private RoleGeneratorService roleGeneratorService; + public static final String GENERATE_ROLE_SCRIPT = "generateRoleScript"; + @RequestMapping(value = GENERATE_ROLE_SCRIPT +"/{firstRun}", method = RequestMethod.GET ) + public ResponseEntity generateRoleScript (@PathVariable("firstRun") boolean firstRun) { + ResponseEntity response = null; + String query = roleGeneratorService.generateRoleScript(firstRun); + response = new ResponseEntity<>(query, HttpStatus.OK); + return response; + } + +} diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/VersionController.java b/vid-app-common/src/main/java/org/onap/vid/controller/VersionController.java new file mode 100644 index 000000000..ba879ed16 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/controller/VersionController.java @@ -0,0 +1,63 @@ +package org.onap.vid.controller; + + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.ImmutableMap; +import org.apache.commons.lang3.StringUtils; +import org.onap.portalsdk.core.controller.UnRestrictedBaseController; +import org.onap.portalsdk.core.util.SystemProperties; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import javax.inject.Inject; +import javax.servlet.ServletContext; +import java.io.IOException; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static org.apache.commons.lang3.StringUtils.substringAfterLast; + +@RestController +@RequestMapping("version") +public class VersionController extends UnRestrictedBaseController { + + private final ServletContext servletContext; + + @Inject + public VersionController(ServletContext servletContext) { + this.servletContext = servletContext; + } + + @RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + public Map getVersionAndFeatures() + { + String features = SystemProperties.getProperty("features.set.filename"); + String version; + try { + final URL resource = servletContext.getResource("/app/vid/scripts/constants/version.json"); + HashMap versionFile = new HashMap <>(); + ObjectMapper mapper = new ObjectMapper(); + versionFile.putAll(mapper.readValue(resource, new TypeReference>() {})); + version = versionFile.get("Version"); + } catch (IOException e) { + version = "Error retrieving build number"; + } + String majorVersion = getDisplayVersion(features, version); + return ImmutableMap.of("Features", features, "Build", version, "DisplayVersion", majorVersion); + } + + String getDisplayVersion(String features, String build) { + Matcher matcher = Pattern.compile("([^/]+?)(\\.features|$)").matcher(features); + final String majorByFeatures = matcher.find() ? matcher.group(1) : features; + + final String buildByVersion = StringUtils.defaultIfBlank(substringAfterLast(build, "."), build); + + return StringUtils.join(majorByFeatures, ".", buildByVersion); + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/VidController.java b/vid-app-common/src/main/java/org/onap/vid/controller/VidController.java new file mode 100644 index 000000000..40d0f4629 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/controller/VidController.java @@ -0,0 +1,114 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Modifications Copyright 2018 Nokia + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.vid.controller; + +import org.onap.portalsdk.core.controller.RestrictedBaseController; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.vid.asdc.AsdcCatalogException; +import org.onap.vid.asdc.beans.SecureServices; +import org.onap.vid.exceptions.VidServiceUnavailableException; +import org.onap.vid.model.PombaInstance.PombaRequest; +import org.onap.vid.model.ServiceModel; +import org.onap.vid.roles.Role; +import org.onap.vid.roles.RoleProvider; +import org.onap.vid.services.AaiService; +import org.onap.vid.services.PombaService; +import org.onap.vid.services.VidService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; + +import javax.servlet.http.HttpServletRequest; +import java.util.List; + +@RestController +public class VidController extends RestrictedBaseController { + + private static final EELFLoggerDelegate LOG = EELFLoggerDelegate.getLogger(VidController.class); + + private final VidService vidService; + private final AaiService aaiService; + private final RoleProvider roleProvider; + private final PombaService pombaService; + + @Autowired + public VidController(VidService vidService, AaiService aaiService, RoleProvider roleProvider, + PombaService pombaService) { + this.vidService = vidService; + this.aaiService = aaiService; + this.roleProvider = roleProvider; + this.pombaService = pombaService; + } + + /** + * @param request the request + * @return the services + */ + @RequestMapping(value = {"/rest/models/services"}, method = RequestMethod.GET) + public SecureServices getServices(HttpServletRequest request) { + LOG.info("Start API for browse ASDC was called"); + SecureServices secureServices = new SecureServices(); + List roles = roleProvider.getUserRoles(request); + secureServices.setServices(aaiService.getServicesByDistributionStatus()); + secureServices.setReadOnly(roleProvider.userPermissionIsReadOnly(roles)); + return secureServices; + } + + + /** + * @param uuid the uuid + * @return the services + * @throws VidServiceUnavailableException the vid service unavailable exception + */ + @RequestMapping(value = {"/rest/models/services/{uuid}"}, method = RequestMethod.GET) + public ServiceModel getService(@PathVariable("uuid") String uuid) throws VidServiceUnavailableException { + try { + return vidService.getService(uuid); + } catch (AsdcCatalogException e) { + LOG.error("Failed to retrieve service definitions from SDC. Error: " + e.getMessage(), e); + throw new VidServiceUnavailableException("Failed to retrieve service definitions from SDC", e); + } + } + + @RequestMapping(value = "/rest/models/reset", method = RequestMethod.POST) + @ResponseStatus(HttpStatus.ACCEPTED) + public void invalidateServiceModelCache() { + vidService.invalidateServiceCache(); + } + + /** + * @return the services view + * @throws VidServiceUnavailableException the vid service unavailable exception + */ + // FIX ME: Circular view path [serviceModels]: would dispatch back to the current handler URL [/serviceModels] again. + @RequestMapping(value = {"/serviceModels"}, method = RequestMethod.GET) + public ModelAndView getServicesView() { + return new ModelAndView("serviceModels"); + } + + @RequestMapping(value = {"/rest/models/services/verifyService"}, method = RequestMethod.POST) + public void verifyServiceInstance(@RequestBody PombaRequest pombaRequest) { + pombaService.verify(pombaRequest); + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/VidRestrictedBaseController.java b/vid-app-common/src/main/java/org/onap/vid/controller/VidRestrictedBaseController.java new file mode 100644 index 000000000..e13cf4512 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/controller/VidRestrictedBaseController.java @@ -0,0 +1,42 @@ +package org.onap.vid.controller; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.exception.ExceptionUtils; +import org.onap.portalsdk.core.controller.RestrictedBaseController; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.vid.model.ExceptionResponse; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; + +import static org.onap.vid.utils.Logging.getMethodCallerName; +import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; + +public abstract class VidRestrictedBaseController extends RestrictedBaseController { + + protected final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(this.getClass().getName()); + + @ExceptionHandler(MethodArgumentTypeMismatchException.class) + @ResponseBody + public ResponseEntity handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e) { + LOGGER.error(EELFLoggerDelegate.errorLogger, "{}: {}", getMethodCallerName(), ExceptionUtils.getMessage(e), e); + Class type = e.getRequiredType(); + String message; + if (type.isEnum()) { + message = "The parameter " + e.getName() + " must have a value among : " + StringUtils.join(type.getEnumConstants(), ", "); + } + else { + message = "The parameter " + e.getName() + " must be of type " + type.getTypeName(); + } + return new ResponseEntity(message, HttpStatus.BAD_REQUEST); + } + + @ExceptionHandler(Exception.class) + @ResponseStatus(value=INTERNAL_SERVER_ERROR) + public ExceptionResponse exceptionHandler(Exception e) { + return ControllersUtils.handleException(e, LOGGER); + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/ViewLogController.java b/vid-app-common/src/main/java/org/onap/vid/controller/ViewLogController.java new file mode 100644 index 000000000..4956c5b1e --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/controller/ViewLogController.java @@ -0,0 +1,65 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.vid.controller; + +import org.onap.portalsdk.core.controller.RestrictedBaseController; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.servlet.ModelAndView; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import java.text.DateFormat; +import java.text.SimpleDateFormat; + + +/** + * The Class ViewLogController. + */ +@RestController +public class ViewLogController extends RestrictedBaseController{ + + /** The logger. */ + private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(ViewLogController.class); + + /** The Constant dateFormat. */ + static final DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss:SSSS"); + + /** The servlet context. */ + private @Autowired ServletContext servletContext; + + /** + * Welcome. + * + * @param request the request + * @return the model and view + */ + @RequestMapping(value = {"/viewlog" }, method = RequestMethod.GET) + public ModelAndView welcome(HttpServletRequest request) { + + return new ModelAndView(getViewName()); + } + + +} diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/WebConfig.java b/vid-app-common/src/main/java/org/onap/vid/controller/WebConfig.java new file mode 100644 index 000000000..68d5b71d0 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/controller/WebConfig.java @@ -0,0 +1,193 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.vid.controller; + +import com.fasterxml.jackson.core.JsonProcessingException; +import io.joshworks.restclient.http.mapper.ObjectMapper; +import org.onap.vid.aai.*; +import org.onap.vid.aai.model.PortDetailsTranslator; +import org.onap.vid.aai.util.*; +import org.onap.vid.asdc.AsdcClient; +import org.onap.vid.asdc.parser.ToscaParserImpl2; +import org.onap.vid.asdc.parser.VidNotionsBuilder; +import org.onap.vid.asdc.rest.SdcRestClient; +import org.onap.vid.client.SyncRestClient; +import org.onap.vid.client.SyncRestClientInterface; +import org.onap.vid.properties.AsdcClientConfiguration; +import org.onap.vid.scheduler.SchedulerService; +import org.onap.vid.scheduler.SchedulerServiceImpl; +import org.onap.vid.services.*; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.togglz.core.manager.FeatureManager; + +import javax.servlet.ServletContext; +import java.io.File; +import java.io.IOException; + +@Configuration +public class WebConfig { + + /** + * Gets the object mapper. + * + * @return the object mapper + */ + @Bean + public com.fasterxml.jackson.databind.ObjectMapper getObjectMapper() { + return new com.fasterxml.jackson.databind.ObjectMapper(); + } + + + @Bean + public VidService vidService(AsdcClient asdcClient, FeatureManager featureManager) { + return new VidServiceImpl(asdcClient, featureManager); + } + + @Bean + public SchedulerService schedulerService(ChangeManagementService changeManagementService) { + return new SchedulerServiceImpl(changeManagementService); + } + + @Bean + public AaiService getAaiService() { + return new AaiServiceImpl(); + } + + @Bean + public AaiResponseTranslator aaiResponseTranslator() { + return new AaiResponseTranslator(); + } + + @Bean + public PortDetailsTranslator portDetailsTranslator() { + return new PortDetailsTranslator(); + } + + @Bean + public AaiClientInterface getAaiRestInterface(@Qualifier("aaiRestInterface") AAIRestInterface restController, PortDetailsTranslator portsDetailsTranslator, CacheProvider cacheProvider) { + return new AaiClient(restController, portsDetailsTranslator, cacheProvider); + } + + @Bean(name = "aaiRestInterface") + public AAIRestInterface aaiRestInterface(HttpsAuthClient httpsAuthClientFactory, ServletRequestHelper servletRequestHelper, SystemPropertyHelper systemPropertyHelper) { + return new AAIRestInterface(httpsAuthClientFactory, servletRequestHelper, systemPropertyHelper); + } + + @Bean + public PombaRestInterface getPombaRestInterface(HttpsAuthClient httpsAuthClientFactory, ServletRequestHelper servletRequestHelper, SystemPropertyHelper systemPropertyHelper) { + return new PombaRestInterface(httpsAuthClientFactory, servletRequestHelper, systemPropertyHelper); + } + + @Bean + public SSLContextProvider sslContextProvider() { + return new SSLContextProvider(); + } + + @Bean + public SystemPropertyHelper systemPropertyHelper() { + return new SystemPropertyHelper(); + } + + @Bean + public ServletRequestHelper servletRequestHelper() { + return new ServletRequestHelper(); + } + + @Bean + public HttpsAuthClient httpsAuthClientFactory(ServletContext servletContext, SystemPropertyHelper systemPropertyHelper, SSLContextProvider sslContextProvider ,FeatureManager featureManager) { + final String certFilePath = new File(servletContext.getRealPath("/WEB-INF/cert/")).getAbsolutePath(); + return new HttpsAuthClient(certFilePath, systemPropertyHelper, sslContextProvider, featureManager); + } + + @Bean + public AsdcClient sdcClient(AsdcClientConfiguration asdcClientConfiguration, SyncRestClientInterface syncRestClient) { + String auth = asdcClientConfiguration.getAsdcClientAuth(); + String host = asdcClientConfiguration.getAsdcClientHost(); + String protocol = asdcClientConfiguration.getAsdcClientProtocol(); + int port = asdcClientConfiguration.getAsdcClientPort(); + + return new SdcRestClient(protocol + "://" + host + ":" + port + "/", auth, syncRestClient); + } + + @Bean + public SyncRestClientInterface syncRestClient() { + return new SyncRestClient(); + } + + @Bean + public VidNotionsBuilder vidNotionsBuilder(FeatureManager featureManager) { + return new VidNotionsBuilder(featureManager); + } + + @Bean + public ToscaParserImpl2 getToscaParser(VidNotionsBuilder vidNotionsBuilder) { + return new ToscaParserImpl2(vidNotionsBuilder); + } + + @Bean + public PombaService getVerifyServiceInstanceService() { + return new PombaServiceImpl(); + } + + @Bean + public PombaClientInterface getVerifyServiceInstanceClientInterface() { + return new PombaClientImpl(); + } + + @Bean + public ServiceInstanceStandardQuery serviceInstanceStandardQuery(AaiClientInterface aaiClient) { + return new ServiceInstanceStandardQuery(aaiClient); + } + + @Bean + public AaiOverTLSClientInterface aaiOverTLSClient(ObjectMapper unirestObjectMapper){ + return new AaiOverTLSClient(new SyncRestClient(unirestObjectMapper), new AaiOverTLSPropertySupplier()); + } + + @Bean + public ObjectMapper unirestFasterxmlObjectMapper(com.fasterxml.jackson.databind.ObjectMapper objectMapper) { + return new ObjectMapper() { + + @Override + public T readValue(String s, Class aClass) { + try { + return objectMapper.readValue(s, aClass); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public String writeValue(Object o) { + try { + return objectMapper.writeValueAsString(o); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + }; + + } + +} diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/filter/ClientCredentialsFilter.java b/vid-app-common/src/main/java/org/onap/vid/controller/filter/ClientCredentialsFilter.java index d4c7e3c5f..cba36a795 100644 --- a/vid-app-common/src/main/java/org/onap/vid/controller/filter/ClientCredentialsFilter.java +++ b/vid-app-common/src/main/java/org/onap/vid/controller/filter/ClientCredentialsFilter.java @@ -20,7 +20,7 @@ import java.io.IOException; @WebFilter(urlPatterns = "/change-management/workflow/*") public class ClientCredentialsFilter extends GenericFilterBean { - private final static EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(ClientCredentialsFilter.class); + private static final EELFLoggerDelegate filterLogger = EELFLoggerDelegate.getLogger(ClientCredentialsFilter.class); @Override @@ -33,12 +33,12 @@ public class ClientCredentialsFilter extends GenericFilterBean { String actualAuthorization = ((HttpServletRequest)request).getHeader("Authorization"); if (verifyClientCredentials(actualAuthorization, expectedAuthorization)) { - LOGGER.warn(EELFLoggerDelegate.debugLogger,"Client credentials authenticated."); + filterLogger.warn(EELFLoggerDelegate.debugLogger,"Client credentials authenticated."); chain.doFilter(request, response); return; } - LOGGER.warn(EELFLoggerDelegate.debugLogger,"Client did not provide the expected credentials."); + filterLogger.warn(EELFLoggerDelegate.debugLogger,"Client did not provide the expected credentials."); ((HttpServletResponse) response).sendError(401); } @@ -46,13 +46,13 @@ public class ClientCredentialsFilter extends GenericFilterBean { { if (StringUtils.isEmpty(expectedAuthorization)) { - LOGGER.warn(EELFLoggerDelegate.debugLogger,String.format("Expected Authorization is not configured (key: %s)", SchedulerProperties.SCHEDULER_BASIC_AUTH)); + filterLogger.warn(EELFLoggerDelegate.debugLogger,String.format("Expected Authorization is not configured (key: %s)", SchedulerProperties.SCHEDULER_BASIC_AUTH)); return true; } if (StringUtils.isEmpty(actualAuthorization)) { - LOGGER.warn(EELFLoggerDelegate.debugLogger,"Authorization header is missing."); + filterLogger.warn(EELFLoggerDelegate.debugLogger,"Authorization header is missing."); return false; } diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/filter/PromiseEcompRequestIdFilter.java b/vid-app-common/src/main/java/org/onap/vid/controller/filter/PromiseEcompRequestIdFilter.java index 7501b1032..9c1cb4633 100644 --- a/vid-app-common/src/main/java/org/onap/vid/controller/filter/PromiseEcompRequestIdFilter.java +++ b/vid-app-common/src/main/java/org/onap/vid/controller/filter/PromiseEcompRequestIdFilter.java @@ -3,7 +3,6 @@ package org.onap.vid.controller.filter; import com.google.common.collect.ImmutableList; import org.apache.commons.lang3.StringUtils; -import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.springframework.web.filter.GenericFilterBean; import javax.servlet.FilterChain; @@ -24,8 +23,7 @@ import static org.onap.portalsdk.core.util.SystemProperties.ECOMP_REQUEST_ID; @WebFilter(urlPatterns = "/*") public class PromiseEcompRequestIdFilter extends GenericFilterBean { - private final static EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(PromiseEcompRequestIdFilter.class); - private final static String REQUEST_ID_RESPONSE_HEADER = ECOMP_REQUEST_ID + "-echo"; + private static final String REQUEST_ID_RESPONSE_HEADER = ECOMP_REQUEST_ID + "-echo"; @Override @@ -48,13 +46,19 @@ public class PromiseEcompRequestIdFilter extends GenericFilterBean { final HttpServletRequest httpRequest = (HttpServletRequest) request; final String originalRequestId = httpRequest.getHeader(ECOMP_REQUEST_ID); - if (StringUtils.isEmpty(originalRequestId)) { + if (StringUtils.isEmpty(originalRequestId) || !verifyAndValidateUuid(originalRequestId)) { request = new PromiseEcompRequestIdRequestWrapper(httpRequest); } return request; } + public static boolean verifyAndValidateUuid(String value) + { + String uuidRegex = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"; + return value.matches(uuidRegex); + } + private static class PromiseEcompRequestIdRequestWrapper extends HttpServletRequestWrapper { private final UUID requestId; @@ -81,12 +85,17 @@ public class PromiseEcompRequestIdFilter extends GenericFilterBean { @Override public Enumeration getHeaderNames() { + + if (null == super.getHeader(ECOMP_REQUEST_ID)) { return Collections.enumeration(ImmutableList.builder() .add(ECOMP_REQUEST_ID) .addAll(Collections.list(super.getHeaderNames())) .build()); } + return super.getHeaderNames(); + } + private boolean isRequestIdHeaderName(String name) { return ECOMP_REQUEST_ID.equalsIgnoreCase(name); } diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/test/TestAaiController.java b/vid-app-common/src/main/java/org/onap/vid/controller/test/TestAaiController.java index c57d93cb9..511e8631b 100644 --- a/vid-app-common/src/main/java/org/onap/vid/controller/test/TestAaiController.java +++ b/vid-app-common/src/main/java/org/onap/vid/controller/test/TestAaiController.java @@ -20,7 +20,7 @@ package org.onap.vid.controller.test; -import org.codehaus.jackson.map.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectMapper; import org.onap.portalsdk.core.controller.RestrictedBaseController; import org.onap.vid.model.ExceptionResponse; import org.springframework.web.bind.annotation.*; diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/test/TestAsdcController.java b/vid-app-common/src/main/java/org/onap/vid/controller/test/TestAsdcController.java index ae6396475..da79ef9b0 100644 --- a/vid-app-common/src/main/java/org/onap/vid/controller/test/TestAsdcController.java +++ b/vid-app-common/src/main/java/org/onap/vid/controller/test/TestAsdcController.java @@ -20,7 +20,7 @@ package org.onap.vid.controller.test; -import org.codehaus.jackson.map.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectMapper; import org.onap.portalsdk.core.controller.RestrictedBaseController; import org.onap.vid.model.ExceptionResponse; import org.springframework.web.bind.annotation.*; diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/test/TestMsoController.java b/vid-app-common/src/main/java/org/onap/vid/controller/test/TestMsoController.java index ba4476fa6..4cb0d6c16 100644 --- a/vid-app-common/src/main/java/org/onap/vid/controller/test/TestMsoController.java +++ b/vid-app-common/src/main/java/org/onap/vid/controller/test/TestMsoController.java @@ -20,7 +20,7 @@ package org.onap.vid.controller.test; -import org.codehaus.jackson.map.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectMapper; import org.onap.portalsdk.core.controller.RestrictedBaseController; import org.onap.vid.model.ExceptionResponse; import org.springframework.http.HttpStatus; -- cgit 1.2.3-korg