From 937c480aac2d675e70c94908febddb42aefc8dcc Mon Sep 17 00:00:00 2001 From: xg353y Date: Wed, 20 Mar 2019 16:01:43 +0100 Subject: Rework the deploy/undeploy method Create the camle box for depoy/undeploy closed loop with the new loop data model Issue-ID: CLAMP-334 Change-Id: Ica77163877c30b31efc37ab489b3810fe1251012 Signed-off-by: xg353y --- .../org/onap/clamp/clds/util/LoggingUtils.java | 31 +++ .../onap/clamp/exception/OperationException.java | 61 ++++++ src/main/java/org/onap/clamp/loop/Loop.java | 12 +- src/main/java/org/onap/clamp/loop/LoopService.java | 4 +- .../org/onap/clamp/operation/LoopOperation.java | 212 +++++++++++++++++++++ .../resources/clds/camel/rest/clamp-api-v2.xml | 38 +++- 6 files changed, 340 insertions(+), 18 deletions(-) create mode 100644 src/main/java/org/onap/clamp/exception/OperationException.java create mode 100644 src/main/java/org/onap/clamp/operation/LoopOperation.java diff --git a/src/main/java/org/onap/clamp/clds/util/LoggingUtils.java b/src/main/java/org/onap/clamp/clds/util/LoggingUtils.java index 300d60663..47b4f9ab1 100644 --- a/src/main/java/org/onap/clamp/clds/util/LoggingUtils.java +++ b/src/main/java/org/onap/clamp/clds/util/LoggingUtils.java @@ -38,6 +38,7 @@ import java.util.Date; import java.util.TimeZone; import java.util.UUID; +import javax.net.ssl.HttpsURLConnection; import javax.servlet.http.HttpServletRequest; import javax.validation.constraints.NotNull; @@ -259,6 +260,36 @@ public class LoggingUtils { this.mLogger.info(ONAPLogConstants.Markers.INVOKE_SYNC + "{"+ invocationID +"}"); return con; } + + /** + * Report pending invocation with INVOKE marker, + * setting standard ONAP logging headers automatically. + * + * @param builder request builder, for setting headers. + * @param sync whether synchronous, nullable. + * @return invocation ID to be passed with invocation. + */ + public HttpsURLConnection invokeHttps(final HttpsURLConnection con, String targetEntity, String targetServiceName) { + final String invocationID = UUID.randomUUID().toString(); + + // Set standard HTTP headers on (southbound request) builder. + con.setRequestProperty(ONAPLogConstants.Headers.REQUEST_ID, + defaultToEmpty(MDC.get(ONAPLogConstants.MDCs.REQUEST_ID))); + con.setRequestProperty(ONAPLogConstants.Headers.INVOCATION_ID, + invocationID); + con.setRequestProperty(ONAPLogConstants.Headers.PARTNER_NAME, + defaultToEmpty(MDC.get(ONAPLogConstants.MDCs.PARTNER_NAME))); + + invokeContext(targetEntity, targetServiceName, invocationID); + + // Log INVOKE*, with the invocationID as the message body. + // (We didn't really want this kind of behavior in the standard, + // but is it worse than new, single-message MDC?) + this.mLogger.info(ONAPLogConstants.Markers.INVOKE); + this.mLogger.info(ONAPLogConstants.Markers.INVOKE_SYNC + "{"+ invocationID +"}"); + return con; + } + public void invokeReturn() { // Add the Invoke-return marker and clear the needed MDC this.mLogger.info(ONAPLogConstants.Markers.INVOKE_RETURN); diff --git a/src/main/java/org/onap/clamp/exception/OperationException.java b/src/main/java/org/onap/clamp/exception/OperationException.java new file mode 100644 index 000000000..0233b092e --- /dev/null +++ b/src/main/java/org/onap/clamp/exception/OperationException.java @@ -0,0 +1,61 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * 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.clamp.exception; + +/** + * New exception to CldsUser errors. + * + */ +public class OperationException extends RuntimeException { + + /** + * The serial version ID. + */ + private static final long serialVersionUID = 2788967876393519620L; + + /** + * This constructor can be used to create a new CldsUsersException. + * + * @param message + * A string message detailing the problem + * @param e + * The exception sent by the code + */ + public OperationException(String message, Throwable e) { + super(message, e); + } + + /** + * This constructor can be used to create a new CldsUsersException. Use this + * constructor only if you are creating a new exception stack, not if an + * exception was already raised by another code. + * + * @param message + * A string message detailing the problem + */ + public OperationException(String message) { + super(message); + } + +} diff --git a/src/main/java/org/onap/clamp/loop/Loop.java b/src/main/java/org/onap/clamp/loop/Loop.java index 64e0108e3..6dc73e987 100644 --- a/src/main/java/org/onap/clamp/loop/Loop.java +++ b/src/main/java/org/onap/clamp/loop/Loop.java @@ -139,7 +139,7 @@ public class Loop implements Serializable { return dcaeDeploymentId; } - void setDcaeDeploymentId(String dcaeDeploymentId) { + public void setDcaeDeploymentId(String dcaeDeploymentId) { this.dcaeDeploymentId = dcaeDeploymentId; } @@ -147,7 +147,7 @@ public class Loop implements Serializable { return dcaeDeploymentStatusUrl; } - void setDcaeDeploymentStatusUrl(String dcaeDeploymentStatusUrl) { + public void setDcaeDeploymentStatusUrl(String dcaeDeploymentStatusUrl) { this.dcaeDeploymentStatusUrl = dcaeDeploymentStatusUrl; } @@ -167,11 +167,11 @@ public class Loop implements Serializable { this.blueprint = blueprint; } - LoopState getLastComputedState() { + public LoopState getLastComputedState() { return lastComputedState; } - void setLastComputedState(LoopState lastComputedState) { + public void setLastComputedState(LoopState lastComputedState) { this.lastComputedState = lastComputedState; } @@ -222,7 +222,7 @@ public class Loop implements Serializable { log.setLoop(this); } - String getDcaeBlueprintId() { + public String getDcaeBlueprintId() { return dcaeBlueprintId; } @@ -230,7 +230,7 @@ public class Loop implements Serializable { this.dcaeBlueprintId = dcaeBlueprintId; } - JsonObject getModelPropertiesJson() { + public JsonObject getModelPropertiesJson() { return modelPropertiesJson; } diff --git a/src/main/java/org/onap/clamp/loop/LoopService.java b/src/main/java/org/onap/clamp/loop/LoopService.java index b4995734b..34e1b4bef 100644 --- a/src/main/java/org/onap/clamp/loop/LoopService.java +++ b/src/main/java/org/onap/clamp/loop/LoopService.java @@ -54,7 +54,7 @@ public class LoopService { this.operationalPolicyService = operationalPolicyService; } - Loop saveOrUpdateLoop(Loop loop) { + public Loop saveOrUpdateLoop(Loop loop) { return loopsRepository.save(loop); } @@ -62,7 +62,7 @@ public class LoopService { return loopsRepository.getAllLoopNames(); } - Loop getLoop(String loopName) { + public Loop getLoop(String loopName) { return loopsRepository .findById(loopName) .orElse(null); diff --git a/src/main/java/org/onap/clamp/operation/LoopOperation.java b/src/main/java/org/onap/clamp/operation/LoopOperation.java new file mode 100644 index 000000000..af615af11 --- /dev/null +++ b/src/main/java/org/onap/clamp/operation/LoopOperation.java @@ -0,0 +1,212 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 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.clamp.operation; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonNull; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; + +import java.lang.reflect.Array; +import java.util.Collection; +import java.util.Date; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.camel.Exchange; +import org.onap.clamp.clds.client.DcaeDispatcherServices; +import org.onap.clamp.clds.util.LoggingUtils; +import org.onap.clamp.clds.util.ONAPLogConstants; +import org.onap.clamp.exception.OperationException; +import org.onap.clamp.loop.Loop; +import org.onap.clamp.loop.LoopService; +import org.onap.clamp.loop.LoopState; +import org.slf4j.event.Level; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; +import org.yaml.snakeyaml.Yaml; + +/** + * Closed loop operations + */ +@Component +public class LoopOperation { + + protected static final EELFLogger logger = EELFManager.getInstance().getLogger(LoopOperation.class); + protected static final EELFLogger auditLogger = EELFManager.getInstance().getMetricsLogger(); + private final DcaeDispatcherServices dcaeDispatcherServices; + private final LoopService loopService; + private LoggingUtils util = new LoggingUtils(logger); + + @Autowired + private HttpServletRequest request; + + @Autowired + public LoopOperation(LoopService loopService, DcaeDispatcherServices dcaeDispatcherServices) { + this.loopService = loopService; + this.dcaeDispatcherServices = dcaeDispatcherServices; + } + + /** + * Deploy the closed loop. + * + * @param loopName the loop name + * @return the updated loop + * @throws Exceptions during the operation + */ + public Loop deployLoop(Exchange camelExchange, String loopName) throws OperationException { + util.entering(request, "CldsService: Deploy model"); + Date startTime = new Date(); + Loop loop = loopService.getLoop(loopName); + + if (loop == null) { + String msg = "Deploy loop exception: Not able to find closed loop:" + loopName; + util.exiting(HttpStatus.INTERNAL_SERVER_ERROR.toString(), msg, Level.INFO, + ONAPLogConstants.ResponseStatus.ERROR); + throw new OperationException(msg); + } + + // verify the current closed loop state + if (loop.getLastComputedState() != LoopState.SUBMITTED) { + String msg = "Deploy loop exception: This closed loop is in state:" + loop.getLastComputedState() + + ". It could be deployed only when it is in SUBMITTED state."; + util.exiting(HttpStatus.CONFLICT.toString(), msg, Level.INFO, + ONAPLogConstants.ResponseStatus.ERROR); + throw new OperationException(msg); + } + + // Set the deploymentId if not present yet + String deploymentId = ""; + // If model is already deployed then pass same deployment id + if (loop.getDcaeDeploymentId() != null && !loop.getDcaeDeploymentId().isEmpty()) { + deploymentId = loop.getDcaeDeploymentId(); + } else { + loop.setDcaeDeploymentId(deploymentId = "closedLoop_" + loopName + "_deploymentId"); + } + + Yaml yaml = new Yaml(); + Map yamlMap = yaml.load(loop.getBlueprint()); + JsonObject bluePrint = wrapSnakeObject(yamlMap).getAsJsonObject(); + + loop.setDcaeDeploymentStatusUrl(dcaeDispatcherServices.createNewDeployment(deploymentId, loop.getDcaeBlueprintId(), bluePrint)); + loop.setLastComputedState(LoopState.DEPLOYED); + // save the updated loop + loopService.saveOrUpdateLoop (loop); + + // audit log + LoggingUtils.setTimeContext(startTime, new Date()); + auditLogger.info("Deploy model completed"); + util.exiting(HttpStatus.OK.toString(), "Successful", Level.INFO, ONAPLogConstants.ResponseStatus.COMPLETED); + return loop; + } + + /** + * Un deploy closed loop. + * + * @param loopName the loop name + * @return the updated loop + */ + public Loop unDeployLoop(String loopName) throws OperationException { + util.entering(request, "LoopOperation: Undeploy the closed loop"); + Date startTime = new Date(); + Loop loop = loopService.getLoop(loopName); + + if (loop == null) { + String msg = "Undeploy loop exception: Not able to find closed loop:" + loopName; + util.exiting(HttpStatus.INTERNAL_SERVER_ERROR.toString(), msg, Level.INFO, + ONAPLogConstants.ResponseStatus.ERROR); + throw new OperationException(msg); + } + + // verify the current closed loop state + if (loop.getLastComputedState() != LoopState.DEPLOYED) { + String msg = "Unploy loop exception: This closed loop is in state:" + loop.getLastComputedState() + + ". It could be undeployed only when it is in DEPLOYED state."; + util.exiting(HttpStatus.CONFLICT.toString(), msg, Level.INFO, + ONAPLogConstants.ResponseStatus.ERROR); + throw new OperationException(msg); + } + + loop.setDcaeDeploymentStatusUrl( + dcaeDispatcherServices.deleteExistingDeployment(loop.getDcaeDeploymentId(), loop.getDcaeBlueprintId())); + + // clean the deployment ID + loop.setDcaeDeploymentId(null); + loop.setLastComputedState(LoopState.SUBMITTED); + + // save the updated loop + loopService.saveOrUpdateLoop (loop); + + // audit log + LoggingUtils.setTimeContext(startTime, new Date()); + auditLogger.info("Undeploy model completed"); + util.exiting(HttpStatus.OK.toString(), "Successful", Level.INFO, ONAPLogConstants.ResponseStatus.COMPLETED); + return loop; + } + + private JsonElement wrapSnakeObject(Object o) { + //NULL => JsonNull + if (o == null) + return JsonNull.INSTANCE; + + // Collection => JsonArray + if (o instanceof Collection) { + JsonArray array = new JsonArray(); + for (Object childObj : (Collection)o) + array.add(wrapSnakeObject(childObj)); + return array; + } + + // Array => JsonArray + if (o.getClass().isArray()) { + JsonArray array = new JsonArray(); + + int length = Array.getLength(array); + for (int i=0; i JsonObject + if (o instanceof Map) { + Map map = (Map)o; + + JsonObject jsonObject = new JsonObject(); + for (final Map.Entry entry : map.entrySet()) { + final String name = String.valueOf(entry.getKey()); + final Object value = entry.getValue(); + jsonObject.add(name, wrapSnakeObject(value)); + } + return jsonObject; + } + + // otherwise take it as a string + return new JsonPrimitive(String.valueOf(o)); + } +} diff --git a/src/main/resources/clds/camel/rest/clamp-api-v2.xml b/src/main/resources/clds/camel/rest/clamp-api-v2.xml index d4872ef45..c5828b284 100644 --- a/src/main/resources/clds/camel/rest/clamp-api-v2.xml +++ b/src/main/resources/clds/camel/rest/clamp-api-v2.xml @@ -10,7 +10,6 @@ @@ -19,19 +18,22 @@ - + + + + - + type="com.google.gson.JsonObject" + consumes="application/json" + outType="org.onap.clamp.loop.Loop" + produces="application/json"> + + + + + + + + + + + + + + + + -- cgit 1.2.3-korg