aboutsummaryrefslogtreecommitdiffstats
path: root/appc-dispatcher/appc-workflow-management/appc-workflow-management-core/src/main/java/org/openecomp/appc/workflow/impl/WorkFlowManagerImpl.java
diff options
context:
space:
mode:
Diffstat (limited to 'appc-dispatcher/appc-workflow-management/appc-workflow-management-core/src/main/java/org/openecomp/appc/workflow/impl/WorkFlowManagerImpl.java')
-rw-r--r--appc-dispatcher/appc-workflow-management/appc-workflow-management-core/src/main/java/org/openecomp/appc/workflow/impl/WorkFlowManagerImpl.java343
1 files changed, 343 insertions, 0 deletions
diff --git a/appc-dispatcher/appc-workflow-management/appc-workflow-management-core/src/main/java/org/openecomp/appc/workflow/impl/WorkFlowManagerImpl.java b/appc-dispatcher/appc-workflow-management/appc-workflow-management-core/src/main/java/org/openecomp/appc/workflow/impl/WorkFlowManagerImpl.java
new file mode 100644
index 000000000..6b197ef19
--- /dev/null
+++ b/appc-dispatcher/appc-workflow-management/appc-workflow-management-core/src/main/java/org/openecomp/appc/workflow/impl/WorkFlowManagerImpl.java
@@ -0,0 +1,343 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : APP-C
+ * ================================================================================
+ * 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.openecomp.appc.workflow.impl;
+
+import java.text.SimpleDateFormat;
+import java.util.Enumeration;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.commons.lang.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.openecomp.appc.common.constant.Constants;
+import org.openecomp.appc.configuration.Configuration;
+import org.openecomp.appc.configuration.ConfigurationFactory;
+import org.openecomp.appc.domainmodel.lcm.RequestContext;
+import org.openecomp.appc.domainmodel.lcm.ResponseContext;
+import org.openecomp.appc.util.ObjectMapper;
+import org.openecomp.appc.workflow.WorkFlowManager;
+import org.openecomp.appc.workflow.objects.WorkflowExistsOutput;
+import org.openecomp.appc.workflow.objects.WorkflowRequest;
+import org.openecomp.appc.workflow.objects.WorkflowResponse;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import org.openecomp.sdnc.sli.SvcLogicException;
+import org.openecomp.sdnc.sli.provider.SvcLogicService;
+
+
+public class WorkFlowManagerImpl implements WorkFlowManager{
+ private SvcLogicService svcLogic = null;
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(WorkFlowManagerImpl.class);
+ private static final Configuration configuration = ConfigurationFactory.getConfiguration();
+
+ private final WorkflowResolver workflowResolver = new WorkflowResolver(
+ configuration.getIntegerProperty("org.openecomp.appc.workflow.resolver.refresh_interval", 300)
+ );
+
+ public void setSvcLogicServiceRef(SvcLogicService svcLogic) {
+ this.svcLogic = svcLogic;
+ }
+
+ /**
+ * Execute workflow and return response.
+ * This method execute workflow with following steps.
+ * Retrieve workflow(DG) details - module, version and mode from database based on command and vnf Type from incoming request.
+ * Execute workflow (DG) using SVC Logic Service reference
+ * Return response of workflow (DG) to caller.
+ *
+ * @param workflowRequest workflow execution request which contains vnfType, command, requestId, targetId, payload and (optional) confID;
+ * @return Workflow Response which contains execution status and payload from DG if any
+ */
+
+ @Override
+ public WorkflowResponse executeWorkflow(WorkflowRequest workflowRequest) {
+ if (logger.isTraceEnabled()) {
+ logger.trace("Entering to executeWorkflow with WorkflowRequest = "+ ObjectUtils.toString(workflowRequest.toString()));
+ }
+ WorkflowResponse workflowResponse = new WorkflowResponse();
+ workflowResponse.setResponseContext(workflowRequest.getResponseContext());
+
+ try {
+
+
+ WorkflowKey workflowKey = workflowResolver.resolve(workflowRequest.getRequestContext().getAction().name(), workflowRequest.getVnfContext().getType(), null,workflowRequest.getRequestContext().getCommonHeader().getApiVer());
+
+ Properties workflowParams = new Properties();
+ String actionProperty = null;
+ String requestIdProperty=null;
+ String vfIdProperty =null;
+ if(!workflowRequest.getRequestContext().getCommonHeader().getApiVer().startsWith("1.")){
+ /*
+ The following method call (populateDGContext) populates DG context with the
+ request parameters to maintain backward compatibility with old DGs,
+ we are not altering the old way of passing (org.openecomp.appc.vnfId and so on..)
+ This is still a temporary solution, the end solution should be agreed with
+ all stakeholders and implemented.
+ */
+ populateDGContext(workflowParams,workflowRequest);
+ } else {
+ actionProperty = configuration.getProperty("org.openecomp.appc.workflow.action", String.valueOf(Constants.ACTION));
+ requestIdProperty = configuration.getProperty("org.openecomp.appc.workflow.request.id", String.valueOf(Constants.REQUEST_ID));
+ vfIdProperty = configuration.getProperty("org.openecomp.appc.workflow.vfid", String.valueOf(Constants.VF_ID));
+ String payloadProperty = configuration.getProperty("org.openecomp.appc.workflow.payload", String.valueOf(Constants.PAYLOAD));
+ String vfTypeProperty = configuration.getProperty("org.openecomp.appc.workflow.vftype", String.valueOf(Constants.VF_TYPE));
+ String apiVerProperty = configuration.getProperty("org.openecomp.appc.workflow.apiVersion", String.valueOf(Constants.API_VERSION));
+ String originatorIdProperty = configuration.getProperty("org.openecomp.appc.workflow.originatorId",Constants.ORIGINATOR_ID);
+ String subRequestId = configuration.getProperty("org.openecomp.appc.workflow.subRequestId",Constants.SUB_REQUEST_ID);
+
+ workflowParams.put(actionProperty,workflowRequest.getRequestContext().getAction().name());
+ workflowParams.put(requestIdProperty, workflowRequest.getRequestContext().getCommonHeader().getRequestId());
+ workflowParams.put(vfIdProperty, workflowRequest.getVnfContext().getId());
+ workflowParams.put(vfTypeProperty,workflowRequest.getVnfContext().getType());
+ workflowParams.put(apiVerProperty,workflowRequest.getRequestContext().getCommonHeader().getApiVer());
+ workflowParams.put(originatorIdProperty,workflowRequest.getRequestContext().getCommonHeader().getOriginatorId());
+ workflowParams.put(subRequestId,workflowRequest.getRequestContext().getCommonHeader().getSubRequestId());
+
+ Object payloadJson = workflowRequest.getRequestContext().getPayload();
+ if(payloadJson!=null) {
+ try {
+ Map<String, String> payloadProperties = ObjectMapper.map(payloadJson);
+ workflowParams.putAll(payloadProperties);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("DG properties: " + workflowParams);
+ }
+ } catch (Exception e) {
+ logger.error("Error parsing payload json string", e);
+ Properties workflowPrp = new Properties();
+ workflowPrp.setProperty("error-message", "Error parsing payload json string");
+ fillStatus(501, "Error parsing payload json string: "+e.getMessage(), workflowRequest.getResponseContext());
+ if (logger.isTraceEnabled()) {
+ logger.trace("Exiting from executeWorkflow with (workflowResponse = "+ObjectUtils.toString(workflowResponse)+")");
+ }
+ return workflowResponse;
+ }
+ }
+ if (logger.isDebugEnabled()) {
+ logger.debug("DG parameters "+ actionProperty +":"+ workflowRequest.getRequestContext().getAction().name()+", "+
+ requestIdProperty +":"+ workflowRequest.getRequestContext().getCommonHeader().getRequestId()+", "+
+ vfIdProperty +":"+ workflowRequest.getVnfContext().getId());
+
+ logger.debug("Starting DG Execution for request "+workflowRequest.getRequestContext().getCommonHeader().getRequestId());
+ }
+ }
+ if (workflowRequest.getRequestContext().getCommonHeader().getApiVer().startsWith("1.")){
+ workflowParams.put("isBwcMode","true");
+ } else {
+ workflowParams.put("isBwcMode", "false");
+ }
+
+ SVCLogicServiceExecute(workflowKey, workflowRequest.getRequestContext(), workflowParams , workflowResponse);
+ if (logger.isTraceEnabled()) {
+ logger.trace("Completed DG Execution for Request id: " + workflowRequest.getRequestContext().getCommonHeader().getRequestId() + "with response code: " + workflowResponse.getResponseContext().getStatus().getCode());
+ }
+ }catch (Exception e){
+ logger.error("Error Executing DG " +e.getMessage());
+ fillStatus(501, "Error Executing DG "+e.getMessage(), workflowRequest.getResponseContext());
+ }
+ if (logger.isTraceEnabled()) {
+ logger.trace("Exiting from executeWorkflow with (workflowResponse = "+ ObjectUtils.toString(workflowResponse.getResponseContext().getStatus().getMessage())+")");
+ }
+ return workflowResponse;
+ }
+
+ private void populateDGContext(Properties workflowParams, WorkflowRequest workflowRequest) {
+ workflowParams.put("input.common-header.timestamp",new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").format(workflowRequest.getRequestContext().getCommonHeader().getTimeStamp()));
+ workflowParams.put("input.common-header.api-ver",workflowRequest.getRequestContext().getCommonHeader().getApiVer());
+ workflowParams.put("input.common-header.request-id",workflowRequest.getRequestContext().getCommonHeader().getRequestId());
+ workflowParams.put("input.common-header.originator-id",workflowRequest.getRequestContext().getCommonHeader().getOriginatorId());
+ workflowParams.put("input.common-header.sub-request-id",workflowRequest.getRequestContext().getCommonHeader().getSubRequestId());
+ workflowParams.put("input.action",workflowRequest.getRequestContext().getAction().toString());
+ workflowParams.put("input.payload",null != workflowRequest.getRequestContext().getPayload() ? workflowRequest.getRequestContext().getPayload() : "");
+ workflowParams.put("input.action-identifiers.vnf-id",workflowRequest.getVnfContext().getId());
+ workflowParams.put("input.action-identifiers.vnfc-name",workflowRequest.getRequestContext().getActionIdentifiers().getVnfcName()!=null?workflowRequest.getRequestContext().getActionIdentifiers().getVnfcName():"");
+ workflowParams.put("input.action-identifiers.service-instance-id",workflowRequest.getRequestContext().getActionIdentifiers().getServiceInstanceId()!=null?workflowRequest.getRequestContext().getActionIdentifiers().getServiceInstanceId():"");
+ workflowParams.put("input.action-identifiers.vserver-id",workflowRequest.getRequestContext().getActionIdentifiers().getVserverId()!=null?workflowRequest.getRequestContext().getActionIdentifiers().getVserverId():"");
+ final Map<String, String> additionalContext;
+ if ((additionalContext = workflowRequest.getRequestContext().getAdditionalContext())!=null) {
+ for (Map.Entry<String, String> entry : additionalContext.entrySet()) {
+ workflowParams.put("input." + entry.getKey(), null != entry.getValue() ? entry.getValue() : "");
+ }
+ }
+ }
+
+ /**
+ * Check if workflow (DG) exists in database
+ *
+ * @param workflowQueryParams workflow request with command and vnf Type
+ * @return True if workflow exists else False.
+ */
+ @Override
+ public WorkflowExistsOutput workflowExists(WorkflowRequest workflowQueryParams) {
+ WorkflowExistsOutput workflowExistsOutput = new WorkflowExistsOutput(false,false);
+ if (logger.isTraceEnabled()) {
+ logger.trace("Entering to workflowExists with WorkflowRequest = "+ObjectUtils.toString(workflowQueryParams.toString()));
+ }
+
+ try {
+ WorkflowKey workflowKey = workflowResolver.resolve(
+ workflowQueryParams.getRequestContext().getAction().name(),
+ workflowQueryParams.getVnfContext().getType(),
+ workflowQueryParams.getVnfContext().getVersion(),
+ workflowQueryParams.getRequestContext().getCommonHeader().getApiVer());
+ if (workflowKey != null) {
+ workflowExistsOutput.setMappingExist(true);
+ workflowExistsOutput.setWorkflowModule(workflowKey.module());
+ workflowExistsOutput.setWorkflowName(workflowKey.name());
+ workflowExistsOutput.setWorkflowVersion(workflowKey.version());
+ if (isDGExists(workflowKey)) {
+ workflowExistsOutput.setDgExist(true);
+ }else{
+ logger.warn(
+ String.format("SLI doesn't have DG for resolved mapping entry: DG module - '%s', DG name - '%s', DG version - '%s'",
+ workflowKey.module(), workflowKey.name(), workflowKey.version()));
+ }
+ }else{
+ logger.warn(
+ String.format("Unable to resolve recipe matching action '%s', VNF type '%s' and VNF version '%s'",
+ workflowQueryParams.getRequestContext().getAction().name(), workflowQueryParams.getVnfContext().getType(), null));
+ }
+ } catch (RuntimeException e) {
+ logger.error("Error querying workflow from database"+e.getMessage());
+ throw e;
+ }catch (SvcLogicException e) {
+ logger.error("Error querying workflow from database"+e.getMessage());
+ throw new RuntimeException(e);
+ }
+ if (logger.isTraceEnabled()) {
+ logger.trace("Exiting workflowExists");
+ }
+ return workflowExistsOutput;
+ }
+
+
+ private boolean isDGExists(WorkflowKey workflowKey) throws SvcLogicException {
+ return svcLogic.hasGraph(workflowKey.module(), workflowKey.name(), workflowKey.version(), "sync");
+ }
+
+ private void SVCLogicServiceExecute(WorkflowKey workflowKey, RequestContext requestContext, Properties workflowParams, WorkflowResponse workflowResponse) {
+ if (logger.isTraceEnabled()) {
+ logger.trace("Entering SVCLogicServiceExecute");
+ }
+
+ Properties respProps = null;
+
+ try {
+ respProps = svcLogic.execute(workflowKey.module(), workflowKey.name(), workflowKey.version(), "sync", workflowParams);
+ } catch (Exception e) {
+ setWorkFlowResponseStatus(workflowResponse.getResponseContext(), "failure", "Unexpected SLI Adapter failure", 200);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Error while executing DG " + e.getMessage() + e.getStackTrace());
+ }
+ logger.error("Error in DG", e.getMessage()+e.getStackTrace().toString());
+ }
+
+ if (respProps != null) {
+ if (!requestContext.getCommonHeader().getApiVer().startsWith("1.")) {
+ fillResponseContextByOutputFieldsFromDgContext(workflowResponse.getResponseContext(), respProps);
+ }
+
+ final String commonStatus = respProps.getProperty(Constants.DG_ATTRIBUTE_STATUS);
+ final String specificStatusMessage = respProps.getProperty(Constants.DG_OUTPUT_STATUS_MESSAGE);
+ String dgOutputStatusCode = respProps.getProperty(Constants.DG_OUTPUT_STATUS_CODE);
+ int specificStatusCode = 0;
+ if (dgOutputStatusCode != null) {
+ specificStatusCode = Integer.parseInt(dgOutputStatusCode);
+ }
+
+ setWorkFlowResponseStatus(workflowResponse.getResponseContext(), commonStatus, specificStatusMessage, specificStatusCode);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("DG Execution Status: " + commonStatus);
+ }
+ }
+
+ if (logger.isTraceEnabled()) {
+ logger.trace("Exiting from SVCLogicServiceExecute");
+ }
+ }
+
+ /**
+ * Filling response context by output.* fields from DG context. Works only for 2.* API version
+ *
+ * @param responseContext response context which you need to fill
+ * @param respProps DG context in a properties format
+ */
+ private void fillResponseContextByOutputFieldsFromDgContext(ResponseContext responseContext, Properties respProps) {
+
+ Enumeration<?> e = respProps.propertyNames();
+ while (e.hasMoreElements()){
+ String key = (String) e.nextElement();
+ if (key.startsWith("output.")){
+ if (!key.startsWith("output.common-header.") && !key.startsWith("output.status.")){
+
+ if (key.equalsIgnoreCase("output.payload")){
+ responseContext.setPayload(respProps.getProperty(key));
+ } else {
+ responseContext.addKeyValueToAdditionalContext(key, respProps.getProperty(key));
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Filling responceContext status code amd message according to responce messages and codes from DG.
+ *
+ * @param responseContext response cotext
+ * @param commonStatus common status message from DG ("success" or "failure")
+ * @param specificStatusMessage specific status message from specific DG node
+ * @param specificStatusCode specific status code from specific DG node
+ */
+ private void setWorkFlowResponseStatus(ResponseContext responseContext, String commonStatus, String specificStatusMessage, int specificStatusCode) {
+ if (null == specificStatusMessage) { specificStatusMessage = ""; }
+ if (commonStatus.equalsIgnoreCase(Constants.DG_STATUS_SUCCESS)){
+ if (specificStatusCode != 0 ){
+ fillStatus(specificStatusCode, specificStatusMessage, responseContext);
+ } else {
+ fillStatus(400, commonStatus, responseContext);
+ }
+ } else {
+ String errorMsg = StringUtils.isEmpty(specificStatusMessage) ? "DG execution failure" : specificStatusMessage;
+ if (specificStatusCode != 0){
+ fillStatus(specificStatusCode, specificStatusMessage, responseContext);
+ } else {
+ fillStatus(401, specificStatusMessage, responseContext);
+ }
+ }
+ }
+
+ /**
+ * filling responseContext by status code and status message
+ *
+ * @param code 3-digit status code
+ * @param message explanation of a status code
+ * @param responceContext response context which will be store status code and status message
+ */
+ private void fillStatus(int code, String message, ResponseContext responceContext) {
+ responceContext.getStatus().setCode(code);
+ responceContext.getStatus().setMessage(message);
+ }
+
+
+}