2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * Modifications Copyright (C) 2018 Nokia. All rights reserved.
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
21 package org.onap.vid.controller;
23 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
24 import com.fasterxml.jackson.annotation.JsonProperty;
25 import com.google.common.base.MoreObjects;
26 import io.joshworks.restclient.http.HttpResponse;
27 import org.apache.commons.lang3.StringUtils;
28 import org.apache.commons.lang3.exception.ExceptionUtils;
29 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
30 import org.onap.vid.changeManagement.RequestDetailsWrapper;
31 import org.onap.vid.model.ExceptionResponse;
32 import org.onap.vid.model.RequestReferencesContainer;
33 import org.onap.vid.mso.MsoBusinessLogic;
34 import org.onap.vid.mso.MsoInterface;
35 import org.onap.vid.mso.MsoResponseWrapper2;
36 import org.onap.vid.mso.model.OperationalEnvironmentActivateInfo;
37 import org.onap.vid.mso.model.OperationalEnvironmentDeactivateInfo;
38 import org.onap.vid.mso.rest.OperationalEnvironment.OperationEnvironmentRequestDetails;
39 import org.onap.vid.mso.rest.RequestDetails;
40 import org.springframework.beans.factory.annotation.Autowired;
41 import org.springframework.http.HttpStatus;
42 import org.springframework.web.bind.MissingServletRequestParameterException;
43 import org.springframework.web.bind.annotation.*;
45 import javax.servlet.http.HttpServletRequest;
46 import java.util.HashMap;
47 import java.util.List;
49 import java.util.regex.Matcher;
50 import java.util.regex.Pattern;
51 import java.util.stream.Collectors;
52 import java.util.stream.Stream;
54 import static org.onap.vid.utils.Logging.getMethodCallerName;
55 import static org.onap.vid.utils.Logging.getMethodName;
58 @RequestMapping("operationalEnvironment")
59 public class OperationalEnvironmentController extends VidRestrictedBaseController {
61 private final MsoInterface restMso;
62 private final MsoBusinessLogic msoBusinessLogic;
64 private static final Pattern RECOVERY_ACTION_MESSAGE_PATTERN = Pattern.compile("from String \"(.*)\": value not");
68 public OperationalEnvironmentController(MsoBusinessLogic msoBusinessLogic, MsoInterface msoClientInterface) {
69 this.restMso = msoClientInterface;
70 this.msoBusinessLogic = msoBusinessLogic;
73 @RequestMapping(value = "/create", method = RequestMethod.POST)
74 public MsoResponseWrapper2 createOperationalEnvironment(HttpServletRequest request, @RequestBody OperationalEnvironmentCreateBody operationalEnvironment) {
75 debugStart(operationalEnvironment);
76 String userId = ControllersUtils.extractUserId(request);
77 RequestDetailsWrapper<OperationEnvironmentRequestDetails> requestDetailsWrapper = msoBusinessLogic.convertParametersToRequestDetails(operationalEnvironment, userId);
78 String path = msoBusinessLogic.getOperationalEnvironmentCreationPath();
80 HttpResponse<RequestReferencesContainer> msoResponse = restMso.post(path, requestDetailsWrapper, RequestReferencesContainer.class);
81 debugEnd(msoResponse);
82 return new MsoResponseWrapper2<>(msoResponse);
85 @RequestMapping(value = "/activate", method = RequestMethod.POST)
86 public MsoResponseWrapper2 activate(HttpServletRequest request,
87 @RequestParam("operationalEnvironment") String operationalEnvironmentId,
88 @RequestBody OperationalEnvironmentActivateBody activateRequest) throws MissingServletRequestParameterException {
90 verifyIsNotEmpty(operationalEnvironmentId, "operationalEnvironment");
92 //manifest is null in case of wrong manifest structure (deserialization failure of the manifest)
93 if (activateRequest.getManifest()==null || activateRequest.getManifest().getServiceModelList()==null) {
94 throw new BadManifestException("Manifest structure is wrong");
97 String userId = ControllersUtils.extractUserId(request);
99 OperationalEnvironmentActivateInfo activateInfo = new OperationalEnvironmentActivateInfo(activateRequest, userId, operationalEnvironmentId);
100 debugStart(activateInfo);
102 String path = msoBusinessLogic.getOperationalEnvironmentActivationPath(activateInfo);
103 RequestDetailsWrapper<RequestDetails> requestDetailsWrapper = msoBusinessLogic.createOperationalEnvironmentActivationRequestDetails(activateInfo);
105 HttpResponse<RequestReferencesContainer> msoResponse = restMso.post(path, requestDetailsWrapper, RequestReferencesContainer.class);
107 debugEnd(msoResponse);
108 return new MsoResponseWrapper2<>(msoResponse);
111 @RequestMapping(value = "/deactivate", method = RequestMethod.POST)
112 public MsoResponseWrapper2 deactivate(HttpServletRequest request,
113 @RequestParam("operationalEnvironment") String operationalEnvironmentId,
114 @RequestBody Map deactivationRequest) throws MissingServletRequestParameterException {
116 verifyIsNotEmpty(operationalEnvironmentId, "operationalEnvironment");
118 String userId = ControllersUtils.extractUserId(request);
120 OperationalEnvironmentDeactivateInfo deactivateInfo = new OperationalEnvironmentDeactivateInfo(userId, operationalEnvironmentId);
121 debugStart(deactivateInfo);
123 String path = msoBusinessLogic.getOperationalEnvironmentDeactivationPath(deactivateInfo);
124 RequestDetailsWrapper<RequestDetails> requestDetailsWrapper = msoBusinessLogic.createOperationalEnvironmentDeactivationRequestDetails(deactivateInfo);
126 HttpResponse<RequestReferencesContainer> msoResponse = restMso.post(path, requestDetailsWrapper, RequestReferencesContainer.class);
128 debugEnd(msoResponse);
129 return new MsoResponseWrapper2<>(msoResponse);
132 @RequestMapping(value = "/requestStatus", method = RequestMethod.GET)
133 public MsoResponseWrapper2 status(HttpServletRequest request, @RequestParam("requestId") String requestId) throws MissingServletRequestParameterException {
135 debugStart(requestId);
137 verifyIsNotEmpty(requestId, "requestId");
138 String path = msoBusinessLogic.getCloudResourcesRequestsStatusPath(requestId);
140 HttpResponse<HashMap> msoResponse = restMso.get(path, HashMap.class);
142 LOGGER.debug(EELFLoggerDelegate.debugLogger, "end {}() => {}", getMethodName(), msoResponse);
143 return new MsoResponseWrapper2<>(msoResponse);
147 org.springframework.web.bind.MissingServletRequestParameterException.class,
148 BadManifestException.class
150 @ResponseStatus(value = HttpStatus.BAD_REQUEST)
151 public ExceptionResponse clientDerivedExceptionAsBadRequest(Exception e) {
152 // same handler, different HTTP Code
153 return exceptionHandler(e);
157 org.springframework.http.converter.HttpMessageNotReadableException.class,
159 @ResponseStatus(value = HttpStatus.BAD_REQUEST)
160 public ExceptionResponse handlingHttpMessageNotReadableException(Exception e) {
161 //in case of wrong value in manifest for RecoveryAction the message contains the class name.
162 //The wrong value is in also part of this messages
163 //within the pattern of: String value '<WRONG_VALUE>': value not
164 //so we use regex to find the wrong value
165 if (e.getMessage().contains(OperationalEnvironmentRecoveryAction.class.getName())) {
166 LOGGER.error(EELFLoggerDelegate.errorLogger, "{}: {}", getMethodName(), ExceptionUtils.getMessage(e), e);
167 String message = "Wrong value for RecoveryAction in manifest. Allowed options are: "+OperationalEnvironmentRecoveryAction.options;
169 Matcher matcher = RECOVERY_ACTION_MESSAGE_PATTERN.matcher(e.getMessage());
170 if (matcher.find()) {
171 String wrongValue = matcher.group(1);
172 message = message+". Wrong value is: "+wrongValue;
174 return new ExceptionResponse(new BadManifestException(message));
176 return exceptionHandler(e);
180 public enum OperationalEnvironmentRecoveryAction {
185 public static final String options = Stream.of(OperationalEnvironmentRecoveryAction.values()).map(OperationalEnvironmentRecoveryAction::name).collect(Collectors.joining(", "));
188 public static class ActivateServiceModel {
189 private String serviceModelVersionId;
190 private OperationalEnvironmentRecoveryAction recoveryAction;
192 public ActivateServiceModel() {
195 public ActivateServiceModel(String serviceModelVersionId, OperationalEnvironmentRecoveryAction recoveryAction) {
196 this.serviceModelVersionId = serviceModelVersionId;
197 this.recoveryAction = recoveryAction;
200 public String getServiceModelVersionId() {
201 return serviceModelVersionId;
204 public void setServiceModelVersionId(String serviceModelVersionId) {
205 this.serviceModelVersionId = serviceModelVersionId;
208 public OperationalEnvironmentRecoveryAction getRecoveryAction() {
209 return recoveryAction;
212 public void setRecoveryAction(OperationalEnvironmentRecoveryAction recoveryAction) {
213 this.recoveryAction = recoveryAction;
217 @JsonIgnoreProperties(ignoreUnknown = true)
218 public static class OperationalEnvironmentManifest {
221 private List<ActivateServiceModel> serviceModelList;
223 public OperationalEnvironmentManifest() {
226 public OperationalEnvironmentManifest(List<ActivateServiceModel> serviceModelList) {
227 this.serviceModelList = serviceModelList;
230 public List<ActivateServiceModel> getServiceModelList() {
231 return serviceModelList;
234 public void setServiceModelList(List<ActivateServiceModel> serviceModelList) {
235 this.serviceModelList = serviceModelList;
239 public static class OperationalEnvironmentActivateBody {
240 private final String relatedInstanceId;
241 private final String relatedInstanceName;
242 private final String workloadContext;
243 private final OperationalEnvironmentManifest manifest;
245 public OperationalEnvironmentActivateBody(@JsonProperty(value = "relatedInstanceId", required = true) String relatedInstanceId,
246 @JsonProperty(value = "relatedInstanceName", required = true) String relatedInstanceName,
247 @JsonProperty(value = "workloadContext", required = true) String workloadContext,
248 @JsonProperty(value = "manifest", required = true) OperationalEnvironmentManifest manifest) {
249 this.relatedInstanceId = relatedInstanceId;
250 this.relatedInstanceName = relatedInstanceName;
251 this.workloadContext = workloadContext;
252 this.manifest = manifest;
256 public String getRelatedInstanceId() {
257 return relatedInstanceId;
260 public String getRelatedInstanceName() {
261 return relatedInstanceName;
264 public String getWorkloadContext() {
265 return workloadContext;
268 public OperationalEnvironmentManifest getManifest() {
273 public String toString() {
274 return MoreObjects.toStringHelper(this)
275 .add("relatedInstanceId", relatedInstanceId)
276 .add("relatedInstanceName", relatedInstanceName)
277 .add("workloadContext", workloadContext)
278 .add("manifest", manifest)
283 public static class OperationalEnvironmentCreateBody {
284 private final String instanceName;
285 private final String ecompInstanceId;
286 private final String ecompInstanceName;
287 private final String operationalEnvironmentType;
288 private final String tenantContext;
289 private final String workloadContext;
291 public OperationalEnvironmentCreateBody(@JsonProperty(value = "instanceName", required = true) String instanceName,
292 @JsonProperty(value = "ecompInstanceId", required = true) String ecompInstanceId,
293 @JsonProperty(value = "ecompInstanceName", required = true) String ecompInstanceName,
294 @JsonProperty(value = "operationalEnvironmentType", required = true) String operationalEnvironmentType,
295 @JsonProperty(value = "tenantContext", required = true) String tenantContext,
296 @JsonProperty(value = "workloadContext", required = true) String workloadContext) {
297 this.instanceName = instanceName;
298 this.ecompInstanceId = ecompInstanceId;
299 this.ecompInstanceName = ecompInstanceName;
300 this.operationalEnvironmentType = operationalEnvironmentType;
301 this.tenantContext = tenantContext;
302 this.workloadContext = workloadContext;
305 public String getInstanceName() {
309 public String getEcompInstanceId() {
310 return ecompInstanceId;
313 public String getEcompInstanceName() {
314 return ecompInstanceName;
317 public String getOperationalEnvironmentType() {
318 return operationalEnvironmentType;
321 public String getTenantContext() {
322 return tenantContext;
325 public String getWorkloadContext() {
326 return workloadContext;
330 public String toString() {
331 return MoreObjects.toStringHelper(this)
332 .add("instanceName", instanceName)
333 .add("ecompInstanceId", ecompInstanceId)
334 .add("ecompInstanceName", ecompInstanceName)
335 .add("operationalEnvironmentType", operationalEnvironmentType)
336 .add("tenantContext", tenantContext)
337 .add("workloadContext", workloadContext)
342 private void debugEnd(HttpResponse<RequestReferencesContainer> msoResponse) {
343 LOGGER.debug(EELFLoggerDelegate.debugLogger, "end {}() => {}", getMethodCallerName(), msoResponse);
346 private void debugStart(Object requestInfo) {
347 LOGGER.debug(EELFLoggerDelegate.debugLogger, "start {}({})", getMethodCallerName(), requestInfo);
350 private void verifyIsNotEmpty(String fieldValue, String fieldName) throws MissingServletRequestParameterException {
351 if (StringUtils.isEmpty(fieldValue)) {
352 throw new MissingServletRequestParameterException(fieldName, "String");
356 public static class BadManifestException extends RuntimeException {
357 public BadManifestException(String message) {