* 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.
import java.io.Serializable;
import java.sql.Timestamp;
import java.time.Instant;
+import java.util.AbstractMap;
import java.util.LinkedList;
+import java.util.Properties;
import javax.persistence.EntityManager;
import javax.persistence.Persistence;
+import org.eclipse.persistence.config.PersistenceUnitProperties;
+import org.onap.policy.aai.util.AAIException;
import org.onap.policy.appc.Response;
import org.onap.policy.appc.ResponseCode;
+import org.onap.policy.appclcm.LCMResponseWrapper;
import org.onap.policy.controlloop.ControlLoopEvent;
+import org.onap.policy.controlloop.ControlLoopException;
import org.onap.policy.controlloop.ControlLoopOperation;
import org.onap.policy.controlloop.VirtualControlLoopEvent;
-import org.onap.policy.controlloop.ControlLoopException;
-import org.onap.policy.controlloop.policy.Policy;
-import org.onap.policy.controlloop.policy.PolicyResult;
import org.onap.policy.controlloop.actor.appc.APPCActorServiceProvider;
+import org.onap.policy.controlloop.actor.appclcm.AppcLcmActorServiceProvider;
+import org.onap.policy.controlloop.actor.so.SOActorServiceProvider;
import org.onap.policy.controlloop.actor.vfc.VFCActorServiceProvider;
+import org.onap.policy.controlloop.policy.Policy;
+import org.onap.policy.controlloop.policy.PolicyResult;
+import org.onap.policy.drools.system.PolicyEngine;
+import org.onap.policy.guard.Util;
+import org.onap.policy.so.SOResponse;
+import org.onap.policy.vfc.VFCResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
public class ControlLoopOperationManager implements Serializable {
-
+
/**
- *
+ *
*/
private static final long serialVersionUID = -3773199283624595410L;
private static final Logger logger = LoggerFactory.getLogger(ControlLoopOperationManager.class);
@Override
public String toString() {
- return "ControlLoopOperationManager [onset=" + (onset != null ? onset.requestID : "null") + ", policy="
+ return "ControlLoopOperationManager [onset=" + (onset != null ? onset.requestID : "null") + ", policy="
+ (policy != null ? policy.getId() : "null") + ", attempts=" + attempts
- + ", policyResult=" + policyResult
+ + ", policyResult=" + policyResult
+ ", currentOperation=" + currentOperation + ", operationHistory=" + operationHistory
+ "]";
}
//
//public final ATTControlLoopEvent onset;
public final ControlLoopEvent onset;
- public final Policy policy;
+ public final transient Policy policy;
//
// Properties used to track the Operation
//
private int attempts = 0;
- private Operation currentOperation = null;
+ private transient Operation currentOperation = null;
private LinkedList<Operation> operationHistory = new LinkedList<Operation>();
private PolicyResult policyResult = null;
private ControlLoopEventManager eventManager = null;
+ private String targetEntity;
public ControlLoopEventManager getEventManager() {
return eventManager;
this.eventManager = eventManager;
}
+ public String getTargetEntity() {
+ return this.targetEntity;
+ }
//
// Internal class used for tracking
public ControlLoopOperation operation = new ControlLoopOperation();
public PolicyResult policyResult = null;
public int attempt = 0;
-
+
@Override
public String toString() {
return "Operation [attempt=" + attempt + ", policyResult=" + policyResult + ", operation=" + operation
+ "]";
}
}
-
+
private String guardApprovalStatus = "NONE";//"NONE", "PERMIT", "DENY"
- private Object operationRequest;
-
+ private transient Object operationRequest;
+
public Object getOperationRequest() {
return operationRequest;
}
public void setGuardApprovalStatus(String guardApprovalStatus) {
this.guardApprovalStatus = guardApprovalStatus;
}
+
+ public String getTarget(Policy policy) throws ControlLoopException, AAIException {
+ if (policy.getTarget() != null) {
+ if (policy.getTarget().getType() != null) {
+ switch(policy.getTarget().getType()) {
+ case PNF:
+ break;
+ case VM:
+ case VNF:
+ VirtualControlLoopEvent virtualOnset = (VirtualControlLoopEvent) this.onset;
+ if (this.onset.target.equalsIgnoreCase("vserver.vserver-name")) {
+ return virtualOnset.AAI.get("vserver.vserver-name");
+ }
+ else if (this.onset.target.equalsIgnoreCase("generic-vnf.vnf-id")) {
+ return virtualOnset.AAI.get("generic-vnf.vnf-id");
+ }
+ else if (this.onset.target.equalsIgnoreCase("generic-vnf.vnf-name")) {
+ /*
+ * If the vnf-name was retrieved from the onset then the vnf-id
+ * must be obtained from the event manager's A&AI GET query
+ */
+ String vnfId = this.eventManager.getVnfResponse().vnfID;
+ if (vnfId == null) {
+ throw new AAIException("No vnf-id found");
+ }
+ return vnfId;
+ }
+ break;
+ default:
+ throw new ControlLoopException("The target type is not supported");
+ }
+ }
+ else {
+ throw new ControlLoopException("The target type is null");
+ }
+ }
+ else {
+ throw new ControlLoopException("The target is null");
+ }
+ throw new ControlLoopException("Target does not match target type");
+ }
-
- public ControlLoopOperationManager(/*ATTControlLoopEvent*/ControlLoopEvent onset, Policy policy, ControlLoopEventManager em) throws ControlLoopException {
+ public ControlLoopOperationManager(ControlLoopEvent onset, Policy policy, ControlLoopEventManager em) throws ControlLoopException, AAIException {
this.onset = onset;
this.policy = policy;
this.guardApprovalStatus = "NONE";
this.eventManager = em;
+ this.targetEntity = getTarget(policy);
//
// Let's make a sanity check
//
switch (policy.getActor()) {
case "APPC":
+ if ("ModifyConfig".equalsIgnoreCase(policy.getRecipe())) {
+ /*
+ * The target vnf-id may not be the same as the source vnf-id
+ * specified in the yaml, the target vnf-id is retrieved by
+ * a named query to A&AI.
+ */
+ String targetVnf = AppcLcmActorServiceProvider.vnfNamedQuery(
+ policy.getTarget().getResourceID(), this.targetEntity);
+ this.targetEntity = targetVnf;
+ }
break;
- case "AOTS":
- break;
- case "MSO":
- break;
- case "SDNO":
- break;
+ case "SO":
+ break;
case "VFC":
break;
default:
throw new ControlLoopException("ControlLoopEventManager: policy has an unknown actor.");
}
}
-
- public Object startOperation(/*VirtualControlLoopEvent*/ControlLoopEvent onset) {
+
+ public Object startOperation(/*VirtualControlLoopEvent*/ControlLoopEvent onset) throws AAIException {
//
// They shouldn't call us if we currently running something
//
this.policyResult = null;
Operation operation = new Operation();
operation.attempt = ++this.attempts;
- operation.operation.actor = this.policy.getActor().toString();
+ operation.operation.actor = this.policy.getActor();
operation.operation.operation = this.policy.getRecipe();
operation.operation.target = this.policy.getTarget().toString();
operation.operation.subRequestId = Integer.toString(operation.attempt);
//
switch (policy.getActor()) {
case "APPC":
- //Request request = APPCActorServiceProvider.constructRequest(onset, operation.operation, this.policy);
- this.operationRequest = APPCActorServiceProvider.constructRequest((VirtualControlLoopEvent)onset, operation.operation, this.policy);
+ /*
+ * If the recipe is ModifyConfig, a legacy APPC
+ * request is constructed. Otherwise an LCMRequest
+ * is constructed.
+ */
+ this.currentOperation = operation;
+ if ("ModifyConfig".equalsIgnoreCase(policy.getRecipe())) {
+
+ this.operationRequest = APPCActorServiceProvider.constructRequest((VirtualControlLoopEvent) onset,
+ operation.operation, this.policy, this.targetEntity);
+ }
+ else {
+ this.operationRequest = AppcLcmActorServiceProvider.constructRequest((VirtualControlLoopEvent) onset,
+ operation.operation, this.policy, this.targetEntity);
+ }
//
// Save the operation
//
+
+ return operationRequest;
+ case "SO":
+ SOActorServiceProvider SOAsp = new SOActorServiceProvider();
+ this.operationRequest = SOAsp.constructRequest((VirtualControlLoopEvent)onset, operation.operation, this.policy);
+
+ // Save the operation
this.currentOperation = operation;
- //System.out.print("************* BEFORE STORING.....");
- //this.storeOperationInDataBase("startOperation");
- //System.out.print("************* AFTER STORING.....");
- //
+
+ if (this.operationRequest == null) {
+ this.policyResult = PolicyResult.FAILURE;
+ }
+
return operationRequest;
- case "MSO":
- //
- // We are not supporting MSO interface at the moment
- //
- logger.debug("We are not supporting MSO actor in the latest release.");
- return null;
case "VFC":
- this.operationRequest = VFCActorServiceProvider.constructRequest((VirtualControlLoopEvent) onset, operation.operation, this.policy);
- this.currentOperation = operation;
- return operationRequest;
+ this.operationRequest = VFCActorServiceProvider.constructRequest((VirtualControlLoopEvent) onset, operation.operation, this.policy, this.eventManager.getVnfResponse());
+ this.currentOperation = operation;
+ if (this.operationRequest == null) {
+ this.policyResult = PolicyResult.FAILURE;
+ }
+ return operationRequest;
}
return null;
}
-
+
public PolicyResult onResponse(Object response) {
//
// Which response is it?
}
return PolicyResult.FAILURE;
}
- }
+ }
+ else if (response instanceof LCMResponseWrapper) {
+
+ LCMResponseWrapper dmaapResponse = (LCMResponseWrapper) response;
+
+ /*
+ * Parse out the operation attempt using the subrequestid
+ */
+ Integer operationAttempt = AppcLcmActorServiceProvider.parseOperationAttempt(dmaapResponse.getBody().getCommonHeader().getSubRequestId());
+ if (operationAttempt == null) {
+ this.completeOperation(operationAttempt, "Policy was unable to parse APP-C SubRequestID (it was null).", PolicyResult.FAILURE_EXCEPTION);
+ }
+
+ /*
+ * Process the APPCLCM response to see what PolicyResult
+ * should be returned
+ */
+ AbstractMap.SimpleEntry<PolicyResult, String> result = AppcLcmActorServiceProvider.processResponse(dmaapResponse);
+
+ if (result.getKey() != null) {
+ this.completeOperation(operationAttempt, result.getValue(), result.getKey());
+ if (PolicyResult.FAILURE_TIMEOUT.equals(this.policyResult)) {
+ return null;
+ }
+ return result.getKey();
+ }
+ return null;
+ } else if (response instanceof SOResponse) {
+ SOResponse msoResponse = (SOResponse) response;
+
+ switch (msoResponse.httpResponseCode) {
+ case 200:
+ case 202:
+ //
+ // Consider it as success
+ //
+ this.completeOperation(this.attempts, msoResponse.httpResponseCode + " Success", PolicyResult.SUCCESS);
+ if (this.policyResult != null && this.policyResult.equals(PolicyResult.FAILURE_TIMEOUT)) {
+ return null;
+ }
+ return PolicyResult.SUCCESS;
+ default:
+ //
+ // Consider it as failure
+ //
+ this.completeOperation(this.attempts, msoResponse.httpResponseCode + " Failed", PolicyResult.FAILURE);
+ if (this.policyResult != null && this.policyResult.equals(PolicyResult.FAILURE_TIMEOUT)) {
+ return null;
+ }
+ return PolicyResult.FAILURE;
+ }
+
+ } else if (response instanceof VFCResponse) {
+ VFCResponse vfcResponse = (VFCResponse) response;
+
+ if (vfcResponse.responseDescriptor.getStatus().equalsIgnoreCase("finished")) {
+ //
+ // Consider it as success
+ //
+ this.completeOperation(this.attempts, " Success", PolicyResult.SUCCESS);
+ if (this.policyResult != null && this.policyResult.equals(PolicyResult.FAILURE_TIMEOUT)) {
+ return null;
+ }
+ return PolicyResult.SUCCESS;
+ } else {
+ //
+ // Consider it as failure
+ //
+ this.completeOperation(this.attempts, " Failed", PolicyResult.FAILURE);
+ if (this.policyResult != null && this.policyResult.equals(PolicyResult.FAILURE_TIMEOUT)) {
+ return null;
+ }
+ // increment operation attempts for retries
+ this.attempts += 1;
+ return PolicyResult.FAILURE;
+ }
+ }
return null;
}
-
+
public Integer getOperationTimeout() {
//
// Sanity check
logger.debug("getOperationTimeout returning {}", this.policy.getTimeout());
return this.policy.getTimeout();
}
-
+
public String getOperationTimeoutString(int defaultTimeout) {
Integer to = this.getOperationTimeout();
if (to == null || to == 0) {
}
return to.toString() + "s";
}
-
+
public PolicyResult getOperationResult() {
return this.policyResult;
}
-
+
public String getOperationMessage() {
if (this.currentOperation != null && this.currentOperation.operation != null) {
return this.currentOperation.operation.toMessage();
}
- if (this.operationHistory != null && this.operationHistory.size() > 0) {
+
+ if (!this.operationHistory.isEmpty()) {
return this.operationHistory.getLast().operation.toMessage();
}
return null;
}
-
+
public String getOperationMessage(String guardResult) {
if (this.currentOperation != null && this.currentOperation.operation != null) {
return this.currentOperation.operation.toMessage()+ ", Guard result: " + guardResult;
}
- if (this.operationHistory != null && this.operationHistory.size() > 0) {
+
+ if (!this.operationHistory.isEmpty()) {
return this.operationHistory.getLast().operation.toMessage() + ", Guard result: " + guardResult;
}
return null;
}
-
+
public String getOperationHistory() {
if (this.currentOperation != null && this.currentOperation.operation != null) {
return this.currentOperation.operation.toHistory();
}
- if (this.operationHistory != null && this.operationHistory.size() > 0) {
+
+ if (!this.operationHistory.isEmpty()) {
return this.operationHistory.getLast().operation.toHistory();
}
return null;
}
-
+
public LinkedList<ControlLoopOperation> getHistory() {
LinkedList<ControlLoopOperation> history = new LinkedList<ControlLoopOperation>();
for (Operation op : this.operationHistory) {
history.add(new ControlLoopOperation(op.operation));
-
+
}
return history;
}
-
+
public void setOperationHasTimedOut() {
//
//
//
this.completeOperation(this.attempts, "Operation timed out", PolicyResult.FAILURE_TIMEOUT);
}
-
+
public void setOperationHasGuardDeny() {
//
//
//
this.completeOperation(this.attempts, "Operation denied by Guard", PolicyResult.FAILURE_GUARD);
}
+
+ public void setOperationHasException(String message) {
+ this.completeOperation(this.attempts, message, PolicyResult.FAILURE_EXCEPTION);
+ }
public boolean isOperationComplete() {
//
//
return true;
}
-
+
public boolean isOperationRunning() {
return (this.currentOperation != null);
}
-
+
private boolean isRetriesMaxedOut() {
if (policy.getRetry() == null || policy.getRetry() == 0) {
//
}
return (this.attempts > policy.getRetry());
}
-
+
private void storeOperationInDataBase(){
+ // Only store in DB if enabled
+ boolean guardEnabled = "false".equalsIgnoreCase(PolicyEngine.manager.getEnvironmentProperty("guard.disabled"));
+ if( !guardEnabled ){
+ return;
+ }
+
+
+ // DB Properties
+ Properties props = new Properties();
+ if(PolicyEngine.manager.getEnvironmentProperty(Util.ONAP_KEY_URL) != null &&
+ PolicyEngine.manager.getEnvironmentProperty(Util.ONAP_KEY_USER) != null &&
+ PolicyEngine.manager.getEnvironmentProperty(Util.ONAP_KEY_PASS) != null){
+ props.put(Util.ECLIPSE_LINK_KEY_URL, PolicyEngine.manager.getEnvironmentProperty(Util.ONAP_KEY_URL));
+ props.put(Util.ECLIPSE_LINK_KEY_USER, PolicyEngine.manager.getEnvironmentProperty(Util.ONAP_KEY_USER));
+ props.put(Util.ECLIPSE_LINK_KEY_PASS, PolicyEngine.manager.getEnvironmentProperty(Util.ONAP_KEY_PASS));
+ props.put(PersistenceUnitProperties.CLASSLOADER, ControlLoopOperationManager.class.getClassLoader());
+ }
+
+ String OpsHistPU = System.getProperty("OperationsHistoryPU");
+ if(OpsHistPU == null || !OpsHistPU.equals("TestOperationsHistoryPU")){
+ OpsHistPU = "OperationsHistoryPU";
+ }
+ else{
+ props.clear();
+ }
EntityManager em;
try{
- em = Persistence.createEntityManagerFactory("OperationsHistoryPU").createEntityManager();//emf.createEntityManager();
+ em = Persistence.createEntityManagerFactory(OpsHistPU, props).createEntityManager();
}catch(Exception e){
logger.error("storeOperationInDataBase threw: ", e);
- return;
+ return;
}
-
- OperationsHistoryDbEntry newEntry = new OperationsHistoryDbEntry();
-
+
+ OperationsHistoryDbEntry newEntry = new OperationsHistoryDbEntry();
+
newEntry.closedLoopName = this.onset.closedLoopControlName;
newEntry.requestId = this.onset.requestID.toString();
newEntry.actor = this.currentOperation.operation.actor;
newEntry.operation = this.currentOperation.operation.operation;
- newEntry.target = this.eventManager.getTargetInstance(this.policy);
+ newEntry.target = this.targetEntity;
newEntry.starttime = Timestamp.from(this.currentOperation.operation.start);
newEntry.subrequestId = this.currentOperation.operation.subRequestId;
newEntry.endtime = new Timestamp(this.currentOperation.operation.end.toEpochMilli());
newEntry.message = this.currentOperation.operation.message;
newEntry.outcome = this.currentOperation.operation.outcome;
-
+
em.getTransaction().begin();
em.persist(newEntry);
em.getTransaction().commit();
-
+
em.close();
}
-
-
+
+
private void completeOperation(Integer attempt, String message, PolicyResult result) {
if (attempt == null) {
logger.debug("attempt cannot be null (i.e. subRequestID)");
}
}
logger.debug("Could not find associated operation");
-
+
}
-
+
}