From 39d82def1e54d6584f41ab9f94d30c2057858c32 Mon Sep 17 00:00:00 2001 From: xg353y Date: Fri, 26 Apr 2019 13:26:25 +0200 Subject: [PATCH] Fix the get loop state logic Fix the logic to get the loop state and update the CL deploy/undeploy flow accordingly Issue-ID: CLAMP-362 Change-Id: I34f83bd241b1029417453908bf932c0b69f9f5b2 Signed-off-by: xg353y --- .../onap/clamp/clds/model/properties/Holmes.java | 16 +- .../java/org/onap/clamp/loop/LoopOperation.java | 231 +++++++++++++-------- src/main/resources/application-noaaf.properties | 5 + src/main/resources/application.properties | 5 + .../resources/clds/camel/rest/clamp-api-v2.xml | 114 +++++++++- .../resources/clds/camel/routes/flexible-flow.xml | 217 +++++++++++++++++++ src/test/resources/application.properties | 5 + src/test/resources/http-cache/third_party_proxy.py | 12 ++ 8 files changed, 510 insertions(+), 95 deletions(-) diff --git a/src/main/java/org/onap/clamp/clds/model/properties/Holmes.java b/src/main/java/org/onap/clamp/clds/model/properties/Holmes.java index a93b09cf..a56c57d1 100644 --- a/src/main/java/org/onap/clamp/clds/model/properties/Holmes.java +++ b/src/main/java/org/onap/clamp/clds/model/properties/Holmes.java @@ -26,11 +26,11 @@ package org.onap.clamp.clds.model.properties; import com.google.gson.JsonObject; + import org.onap.clamp.clds.util.JsonUtils; /** - * Parse Holmes bpmn parameters json properties. - * Example json: + * Parse Holmes bpmn parameters json properties. Example json: * [{"name":"correlationalLogic","value":"vcwx"},{"name":"configPolicyName","value":"cccc"}] */ public class Holmes extends AbstractModelElement { @@ -43,14 +43,18 @@ public class Holmes extends AbstractModelElement { /** * Default constructor for Holmes Element. * - * @param modelBpmn The model bpmn - * @param modelJson The model json + * @param modelBpmn + * The model bpmn + * @param modelJson + * The model json */ public Holmes(ModelBpmn modelBpmn, JsonObject modelJson) { super(TYPE_HOLMES, modelBpmn, modelJson); - correlationLogic = JsonUtils.getStringValueByName(modelElementJsonNode, "correlationalLogic"); - configPolicyName = JsonUtils.getStringValueByName(modelElementJsonNode, "configPolicyName"); + if (modelElementJsonNode != null) { + correlationLogic = JsonUtils.getStringValueByName(modelElementJsonNode, "correlationalLogic"); + configPolicyName = JsonUtils.getStringValueByName(modelElementJsonNode, "configPolicyName"); + } } public static final String getType() { diff --git a/src/main/java/org/onap/clamp/loop/LoopOperation.java b/src/main/java/org/onap/clamp/loop/LoopOperation.java index 3f4c5293..f38b5914 100644 --- a/src/main/java/org/onap/clamp/loop/LoopOperation.java +++ b/src/main/java/org/onap/clamp/loop/LoopOperation.java @@ -31,23 +31,18 @@ import com.google.gson.JsonNull; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; +import java.io.IOException; 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.apache.camel.Message; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; import org.onap.clamp.clds.config.ClampProperties; -import org.onap.clamp.clds.util.LoggingUtils; -import org.onap.clamp.clds.util.ONAPLogConstants; -import org.onap.clamp.exception.OperationException; -import org.onap.clamp.util.HttpConnectionManager; -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; @@ -59,117 +54,179 @@ 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 static final String DCAE_LINK_FIELD = "links"; + private static final String DCAE_STATUS_FIELD = "status"; + private static final String DCAE_DEPLOYMENT_TEMPLATE = "dcae.deployment.template"; + private static final String DCAE_SERVICETYPE_ID = "serviceTypeId"; + private static final String DCAE_INPUTS = "inputs"; + private static final String DCAE_DEPLOYMENT_PREFIX = "closedLoop_"; + private static final String DCAE_DEPLOYMENT_SUFIX = "_deploymentId"; private final LoopService loopService; - private LoggingUtils util = new LoggingUtils(logger); + private final ClampProperties refProp; - @Autowired - private HttpServletRequest request; + public enum TempLoopState { + NOT_SUBMITTED, SUBMITTED, DEPLOYED, NOT_DEPLOYED, PROCESSING, IN_ERROR; + } + /** + * The constructor. + * @param loopService The loop service + * @param refProp The clamp properties + */ @Autowired - public LoopOperation(LoopService loopService, DcaeDispatcherServices dcaeDispatcherServices, - ClampProperties refProp, HttpConnectionManager httpConnectionManager) { + public LoopOperation(LoopService loopService, ClampProperties refProp) { this.loopService = loopService; - this.dcaeDispatcherServices = dcaeDispatcherServices; + this.refProp = refProp; } - + /** - * Deploy the closed loop. + * Get the payload used to send the deploy closed loop request. * - * @param loopName - * the loop name - * @return the updated loop - * @throws OperationException - * Exception during the operation + * @param loop The loop + * @return The payload used to send deploy closed loop request + * @throws IOException IOException */ - 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); - } + public String getDeployPayload(Loop loop) throws IOException { + Yaml yaml = new Yaml(); + Map yamlMap = yaml.load(loop.getBlueprint()); + JsonObject bluePrint = wrapSnakeObject(yamlMap).getAsJsonObject(); + + String serviceTypeId = loop.getDcaeBlueprintId(); - // 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); + JsonObject rootObject = refProp.getJsonTemplate(DCAE_DEPLOYMENT_TEMPLATE).getAsJsonObject(); + rootObject.addProperty(DCAE_SERVICETYPE_ID, serviceTypeId); + if (bluePrint != null) { + rootObject.add(DCAE_INPUTS, bluePrint); } + String apiBodyString = rootObject.toString(); + logger.info("Dcae api Body String - " + apiBodyString); + return apiBodyString; + } + + /** + * Get the deployment id. + * + * @param loop The loop + * @return The deployment id + * @throws IOException IOException + */ + public String getDeploymentId(Loop loop) { // 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"); + deploymentId = DCAE_DEPLOYMENT_PREFIX + loop.getName() + DCAE_DEPLOYMENT_SUFIX; } + return deploymentId; + } - Yaml yaml = new Yaml(); - Map yamlMap = yaml.load(loop.getBlueprint()); - JsonObject bluePrint = wrapSnakeObject(yamlMap).getAsJsonObject(); + /** + * Update the loop info. + * + * @param camelExchange The camel exchange + * @param loop The loop + * @param deploymentId The deployment id + * @throws ParseException The parse exception + */ + public void updateLoopInfo(Exchange camelExchange, Loop loop, String deploymentId) throws ParseException { + Message in = camelExchange.getIn(); + String msg = in.getBody(String.class); - loop.setDcaeDeploymentStatusUrl( - dcaeDispatcherServices.createNewDeployment(deploymentId, loop.getDcaeBlueprintId(), bluePrint)); - loop.setLastComputedState(LoopState.DEPLOYED); - // save the updated loop - loopService.saveOrUpdateLoop(loop); + JSONParser parser = new JSONParser(); + Object obj0 = parser.parse(msg); + JSONObject jsonObj = (JSONObject) obj0; + + JSONObject linksObj = (JSONObject) jsonObj.get(DCAE_LINK_FIELD); + String statusUrl = (String) linksObj.get(DCAE_STATUS_FIELD); + + // use http4 instead of http, because camel http4 component is used to do the http call + statusUrl.replace("http", "http4"); - // 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; + loop.setDcaeDeploymentId(deploymentId); + loop.setDcaeDeploymentStatusUrl(statusUrl); + loopService.saveOrUpdateLoop(loop); } /** - * Un deploy closed loop. + * Get the Closed Loop status based on the reply from Policy. * - * @param loopName - * the loop name - * @return the updated loop + * @param statusCode The status code + * @return The state based on policy response + * @throws ParseException The parse exception */ - 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); + public String analysePolicyResponse(int statusCode) throws ParseException { + if (statusCode == 200) { + return TempLoopState.SUBMITTED.toString(); + } else if (statusCode == 404) { + return TempLoopState.NOT_SUBMITTED.toString(); } + return TempLoopState.IN_ERROR.toString(); + } - // 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); + /** + * Get the Closed Loop status based on the reply from DCAE. + * + * @param camelExchange The camel exchange + * @return The state based on DCAE response + * @throws ParseException The parse exception + */ + public String analyseDcaeResponse(Exchange camelExchange, Integer statusCode) throws ParseException { + if (statusCode == null) { + return TempLoopState.NOT_DEPLOYED.toString(); } + if (statusCode == 200) { + Message in = camelExchange.getIn(); + String msg = in.getBody(String.class); - loop.setDcaeDeploymentStatusUrl( - dcaeDispatcherServices.deleteExistingDeployment(loop.getDcaeDeploymentId(), loop.getDcaeBlueprintId())); + JSONParser parser = new JSONParser(); + Object obj0 = parser.parse(msg); + JSONObject jsonObj = (JSONObject) obj0; - // clean the deployment ID - loop.setDcaeDeploymentId(null); - loop.setLastComputedState(LoopState.SUBMITTED); + String opType = (String) jsonObj.get("operationType"); + String status = (String) jsonObj.get("status"); - // save the updated loop - loopService.saveOrUpdateLoop(loop); + // status = processing/successded/failed + if (status == "successed") { + if (opType == "install") { + return TempLoopState.DEPLOYED.toString(); + } else if (status == "successed") { + return TempLoopState.NOT_DEPLOYED.toString(); + } + } else if (status == "processing") { + return TempLoopState.PROCESSING.toString(); + } + } else if (statusCode == 404) { + return TempLoopState.NOT_DEPLOYED.toString(); + } + return TempLoopState.IN_ERROR.toString(); + } - // 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; + /** + * Get the status of the closed loop based on the response from Policy and DCAE. + * + * @param policyState The state get from Policy + * @param dcaeState The state get from DCAE + * @throws ParseException The parse exception + */ + public LoopState updateLoopStatus(TempLoopState policyState, TempLoopState dcaeState) { + LoopState clState = LoopState.IN_ERROR; + if (policyState == TempLoopState.SUBMITTED) { + if (dcaeState == TempLoopState.DEPLOYED) { + clState = LoopState.DEPLOYED; + } else if (dcaeState == TempLoopState.PROCESSING) { + clState = LoopState.WAITING; + } else if (dcaeState == TempLoopState.NOT_DEPLOYED) { + clState = LoopState.SUBMITTED; + } + } else if (policyState == TempLoopState.NOT_SUBMITTED) { + if (dcaeState == TempLoopState.NOT_DEPLOYED) { + clState = LoopState.DESIGN; + } + } + return clState; } private JsonElement wrapSnakeObject(Object obj) { diff --git a/src/main/resources/application-noaaf.properties b/src/main/resources/application-noaaf.properties index de3f7c07..52f79bef 100644 --- a/src/main/resources/application-noaaf.properties +++ b/src/main/resources/application-noaaf.properties @@ -210,6 +210,11 @@ clamp.config.dcae.dispatcher.url=http://dcae.api.simpledemo.onap.org:8188 clamp.config.dcae.dispatcher.retry.interval=20000 clamp.config.dcae.dispatcher.retry.limit=30 +#DCAE Deployment Url Properties +clamp.config.dcae.deployment.url=http4://dcae.api.simpledemo.onap.org:8188 +clamp.config.dcae.deployment.userName=test +clamp.config.dcae.deployment.password=test + #Define user permission related parameters, the permission type can be changed but MUST be redefined in clds-users.properties in that case ! clamp.config.security.permission.type.cl=org.onap.clamp.clds.cl clamp.config.security.permission.type.cl.manage=org.onap.clamp.clds.cl.manage diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index f59b8ac6..534dc481 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -228,6 +228,11 @@ clamp.config.dcae.dispatcher.url=http://dcae.api.simpledemo.onap.org:8188 clamp.config.dcae.dispatcher.retry.interval=20000 clamp.config.dcae.dispatcher.retry.limit=30 +#DCAE Deployment Url Properties +clamp.config.dcae.deployment.url=http4://dcae.api.simpledemo.onap.org:8188 +clamp.config.dcae.deployment.userName=test +clamp.config.dcae.deployment.password=test + #Define user permission related parameters, the permission type can be changed but MUST be redefined in clds-users.properties in that case ! clamp.config.security.permission.type.cl=org.onap.clamp.clds.cl clamp.config.security.permission.type.cl.manage=org.onap.clamp.clds.cl.manage 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 5c5f122c..2640d6bd 100644 --- a/src/main/resources/clds/camel/rest/clamp-api-v2.xml +++ b/src/main/resources/clds/camel/rest/clamp-api-v2.xml @@ -206,7 +206,40 @@ + uri="direct:load-loop" /> + + ${exchangeProperty[loopObject].getOperationalPolicies()} + + + ${body} + + + + + + + + + ${exchangeProperty[policyStatus]} == 'SUBMITTED' and + ${exchangeProperty[dcaeStatus]} == 'NOT_DEPLOYED' + + + + + + + + @@ -216,6 +249,11 @@ + + @@ -234,7 +272,24 @@ + uri="direct:load-loop" /> + + + + ${exchangeProperty[dcaeStatus]} == 'DEPLOYED' + + + + + + + + @@ -244,6 +299,11 @@ + + @@ -526,5 +586,55 @@ + + + + + + + + + + + false + + + + + + + + + + + java.lang.Exception + + false + + + + + + + + diff --git a/src/main/resources/clds/camel/routes/flexible-flow.xml b/src/main/resources/clds/camel/routes/flexible-flow.xml index 75341de9..68138008 100644 --- a/src/main/resources/clds/camel/routes/flexible-flow.xml +++ b/src/main/resources/clds/camel/routes/flexible-flow.xml @@ -490,7 +490,224 @@ + + + + + + ${exchangeProperty[loopObject].getOperationalPolicies()} + + + ${body} + + + + + + + + + PUT + + + application/json + + + ${exchangeProperty[X-ONAP-RequestID]} + + + + ${exchangeProperty[X-ONAP-InvocationID]} + + + + ${exchangeProperty[X-ONAP-PartnerName]} + + + + + + + + + + Deploy closed loop status + + + + + + + + + + + + + {\"serviceTypeId\": \"${exchangeProperty[loopObject].getDcaeBlueprintId()}\"} + + + + DELETE + + + application/json + + + ${exchangeProperty[X-ONAP-RequestID]} + + + + ${exchangeProperty[X-ONAP-InvocationID]} + + + + ${exchangeProperty[X-ONAP-PartnerName]} + + + + + + + + + + Undeploy closed loop status + + + + + + + + + + + + null + + + GET + + + ${exchangeProperty[X-ONAP-RequestID]} + + + + ${exchangeProperty[X-ONAP-InvocationID]} + + + + ${exchangeProperty[X-ONAP-PartnerName]} + + + + + + + + + Query closed loop from Policy status + + + + + + + + + + + + + + + ${exchangeProperty[loopObject].getDcaeDeploymentStatusUrl()} == null + + + + + + + + + + + GET + + + ${exchangeProperty[X-ONAP-RequestID]} + + + + ${exchangeProperty[X-ONAP-InvocationID]} + + + + ${exchangeProperty[X-ONAP-PartnerName]} + + + + + + + + + Query closed loop from DCAE status + + + + + + + + + + + diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties index ecc40331..061505a1 100644 --- a/src/test/resources/application.properties +++ b/src/test/resources/application.properties @@ -217,6 +217,11 @@ clamp.config.dcae.dispatcher.url=http://localhost:${docker.http-cache.port.host} clamp.config.dcae.dispatcher.retry.interval=100 clamp.config.dcae.dispatcher.retry.limit=1 +#DCAE Deployment Url Properties +clamp.config.dcae.deployment.url=http4://localhost:${docker.http-cache.port.host} +clamp.config.dcae.deployment.userName=test +clamp.config.dcae.deployment.password=test + #Define user permission related parameters, the permission type can be changed but MUST be redefined in clds-users.properties in that case ! clamp.config.security.permission.type.cl=permission-type-cl clamp.config.security.permission.type.cl.manage=permission-type-cl-manage diff --git a/src/test/resources/http-cache/third_party_proxy.py b/src/test/resources/http-cache/third_party_proxy.py index f19aa0da..0db977bb 100755 --- a/src/test/resources/http-cache/third_party_proxy.py +++ b/src/test/resources/http-cache/third_party_proxy.py @@ -199,6 +199,18 @@ class Proxy(SimpleHTTPServer.SimpleHTTPRequestHandler): with open(cached_file_content, 'w+') as f: f.write(self.data_string) return True + elif self.path.startswith("/policy/api/v1/policytypes/") and http_type == "GET": + print "self.path start with /policy/api/v1/policytypes/, generating response json..." + jsonGenerated = "{\"policyTypeId\": \"onap.policies.controlloop.operational\",\"policyTypeVersion\": \"1.0.0\",\"policyId\": \"OPERATIONAL_z711F_v1_0_ResourceInstanceName1_tca\"}" + print "jsonGenerated: " + jsonGenerated + if not os.path.exists(cached_file_folder): + os.makedirs(cached_file_folder, 0777) + + with open(cached_file_header, 'w') as f: + f.write("{\"Content-Length\": \"" + str(len(jsonGenerated)) + "\", \"Content-Type\": \"application/json\"}") + with open(cached_file_content, 'w') as f: + f.write(jsonGenerated) + return True else: return False -- 2.16.6