2 * ============LICENSE_START=======================================================
3 * controlloop operation manager
4 * ================================================================================
5 * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
6 * Modifications Copyright (C) 2019 Huawei Technologies Co., Ltd. All rights reserved.
7 * Modifications Copyright (C) 2019 Tech Mahindra
8 * Modifications Copyright (C) 2019 Bell Canada.
9 * ================================================================================
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 * ============LICENSE_END=========================================================
24 package org.onap.policy.controlloop.eventmanager;
26 import java.io.Serializable;
27 import java.sql.Timestamp;
28 import java.time.Instant;
29 import java.util.AbstractMap;
30 import java.util.HashMap;
31 import java.util.LinkedList;
32 import java.util.List;
34 import java.util.NoSuchElementException;
35 import java.util.Optional;
36 import java.util.Properties;
37 import javax.persistence.EntityManager;
38 import javax.persistence.Persistence;
40 import org.apache.commons.lang3.StringUtils;
41 import org.eclipse.persistence.config.PersistenceUnitProperties;
42 import org.onap.aai.domain.yang.GenericVnf;
43 import org.onap.aai.domain.yang.ServiceInstance;
44 import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput;
45 import org.onap.policy.aai.AaiCqResponse;
46 import org.onap.policy.aai.util.AaiException;
47 import org.onap.policy.appc.Response;
48 import org.onap.policy.appc.ResponseCode;
49 import org.onap.policy.appclcm.AppcLcmDmaapWrapper;
50 import org.onap.policy.cds.CdsResponse;
51 import org.onap.policy.controlloop.ControlLoopEvent;
52 import org.onap.policy.controlloop.ControlLoopException;
53 import org.onap.policy.controlloop.ControlLoopOperation;
54 import org.onap.policy.controlloop.ControlLoopResponse;
55 import org.onap.policy.controlloop.VirtualControlLoopEvent;
56 import org.onap.policy.controlloop.actor.appc.AppcActorServiceProvider;
57 import org.onap.policy.controlloop.actor.appclcm.AppcLcmActorServiceProvider;
58 import org.onap.policy.controlloop.actor.cds.CdsActorServiceProvider;
59 import org.onap.policy.controlloop.actor.cds.constants.CdsActorConstants;
60 import org.onap.policy.controlloop.actor.sdnc.SdncActorServiceProvider;
61 import org.onap.policy.controlloop.actor.sdnr.SdnrActorServiceProvider;
62 import org.onap.policy.controlloop.actor.so.SoActorServiceProvider;
63 import org.onap.policy.controlloop.actor.vfc.VfcActorServiceProvider;
64 import org.onap.policy.controlloop.policy.Policy;
65 import org.onap.policy.controlloop.policy.PolicyResult;
66 import org.onap.policy.controlloop.policy.TargetType;
67 import org.onap.policy.database.operationshistory.Dbao;
68 import org.onap.policy.drools.system.PolicyEngineConstants;
69 import org.onap.policy.guard.Util;
70 import org.onap.policy.sdnc.SdncResponse;
71 import org.onap.policy.sdnr.PciResponseWrapper;
72 import org.onap.policy.so.SoResponseWrapper;
73 import org.onap.policy.vfc.VfcResponse;
74 import org.slf4j.Logger;
75 import org.slf4j.LoggerFactory;
77 public class ControlLoopOperationManager implements Serializable {
78 private static final String SUCCESS_MSG = " Success";
79 private static final String FAILED_MSG = " Failed";
80 private static final String AAI_CUSTOM_QUERY = "aai.customQuery";
81 private static final long serialVersionUID = -3773199283624595410L;
82 private static final Logger logger = LoggerFactory.getLogger(ControlLoopOperationManager.class);
84 private static final String VSERVER_VSERVER_NAME = "vserver.vserver-name";
85 private static final String GENERIC_VNF_VNF_NAME = "generic-vnf.vnf-name";
86 private static final String GENERIC_VNF_VNF_ID = "generic-vnf.vnf-id";
88 private static final String AAI_SERVICE_INSTANCE_ID_KEY = "service-instance.service-instance-id";
89 private static final String PNF_NAME = "pnf.pnf-name";
92 // These properties are not changeable, but accessible
93 // for Drools Rule statements.
95 public final ControlLoopEvent onset;
96 public final Policy policy;
99 // Properties used to track the Operation
101 private int attempts = 0;
102 private Operation currentOperation = null;
103 private LinkedList<Operation> operationHistory = new LinkedList<>();
104 private PolicyResult policyResult = null;
105 private ControlLoopEventManager eventManager = null;
106 private String targetEntity;
107 private String guardApprovalStatus = "NONE";// "NONE", "PERMIT", "DENY"
108 private AaiCqResponse aaiCqResponse;
109 private transient Object operationRequest;
112 * Construct an instance.
114 * @param onset the onset event
115 * @param policy the policy
116 * @param em the event manager
117 * @throws ControlLoopException if an error occurs
119 public ControlLoopOperationManager(ControlLoopEvent onset, Policy policy, ControlLoopEventManager em)
120 throws ControlLoopException {
123 this.policy = policy;
124 this.guardApprovalStatus = "NONE";
125 this.eventManager = em;
128 if (TargetType.VNF.equals(policy.getTarget().getType())
129 || TargetType.VFMODULE.equals(policy.getTarget().getType())) {
130 String aaiCqEnvProp =
131 PolicyEngineConstants.getManager().getEnvironmentProperty(AAI_CUSTOM_QUERY);
132 if (StringUtils.isBlank(aaiCqEnvProp) || Boolean.valueOf(aaiCqEnvProp)) {
133 this.aaiCqResponse = this.eventManager.getCqResponse((VirtualControlLoopEvent) onset);
137 this.targetEntity = getTarget(policy);
141 } catch (AaiException e) {
142 throw new ControlLoopException(e.getMessage(), e);
147 private void initActor(Policy policy) throws AaiException, ControlLoopException {
149 // Let's make a sanity check
151 switch (policy.getActor()) {
166 throw new ControlLoopException("ControlLoopEventManager: policy has an unknown actor.");
171 private void initAppc(Policy policy) throws AaiException {
172 if ("ModifyConfig".equalsIgnoreCase(policy.getRecipe())) {
174 * The target vnf-id may not be the same as the source vnf-id specified in the yaml, the target
175 * vnf-id is retrieved by a named query to A&AI.
177 if (Boolean.valueOf(PolicyEngineConstants.getManager().getEnvironmentProperty(AAI_CUSTOM_QUERY))) {
179 this.aaiCqResponse.getGenericVnfByModelInvariantId(policy.getTarget().getResourceID());
180 if (genvnf == null) {
181 logger.info("Target entity could not be found");
182 throw new AaiException("Target vnf-id could not be found");
184 this.targetEntity = genvnf.getVnfId();
188 AppcLcmActorServiceProvider.vnfNamedQuery(policy.getTarget().getResourceID(),
189 this.targetEntity, PolicyEngineConstants.getManager().getEnvironmentProperty("aai.url"),
190 PolicyEngineConstants.getManager().getEnvironmentProperty("aai.username"),
191 PolicyEngineConstants.getManager().getEnvironmentProperty("aai.password"));
197 public ControlLoopEventManager getEventManager() {
201 public void setEventManager(ControlLoopEventManager eventManager) {
202 this.eventManager = eventManager;
205 public String getTargetEntity() {
206 return this.targetEntity;
210 public String toString() {
211 return "ControlLoopOperationManager [onset=" + (onset != null ? onset.getRequestId() : "null") + ", policy="
212 + (policy != null ? policy.getId() : "null") + ", attempts=" + attempts + ", policyResult="
213 + policyResult + ", currentOperation=" + currentOperation + ", operationHistory=" + operationHistory
218 // Internal class used for tracking
220 private class Operation implements Serializable {
221 private static final long serialVersionUID = 1L;
223 private ControlLoopOperation clOperation = new ControlLoopOperation();
224 private PolicyResult policyResult = null;
225 private int attempt = 0;
228 public String toString() {
229 return "Operation [attempt=" + attempt + ", policyResult=" + policyResult + ", operation=" + clOperation
234 public Object getOperationRequest() {
235 return operationRequest;
238 public String getGuardApprovalStatus() {
239 return guardApprovalStatus;
242 public void setGuardApprovalStatus(String guardApprovalStatus) {
243 this.guardApprovalStatus = guardApprovalStatus;
247 * Get the target for a policy.
249 * @param policy the policy
251 * @throws ControlLoopException if an error occurs
253 public String getTarget(Policy policy) throws ControlLoopException {
254 if (policy.getTarget() == null) {
255 throw new ControlLoopException("The target is null");
258 if (policy.getTarget().getType() == null) {
259 throw new ControlLoopException("The target type is null");
262 switch (policy.getTarget().getType()) {
264 return getPnfTarget();
267 return getVfModuleTarget();
269 return getVfModuleTarget();
271 throw new ControlLoopException("The target type is not supported");
276 private String getVfModuleTarget() throws ControlLoopException {
277 VirtualControlLoopEvent virtualOnsetEvent = (VirtualControlLoopEvent) this.onset;
278 if (this.onset.getTarget().equalsIgnoreCase(VSERVER_VSERVER_NAME)) {
279 return virtualOnsetEvent.getAai().get(VSERVER_VSERVER_NAME);
280 } else if (this.onset.getTarget().equalsIgnoreCase(GENERIC_VNF_VNF_ID)) {
281 return virtualOnsetEvent.getAai().get(GENERIC_VNF_VNF_ID);
282 } else if (this.onset.getTarget().equalsIgnoreCase(GENERIC_VNF_VNF_NAME)) {
284 * If the onset is enriched with the vnf-id, we don't need an A&AI response
286 if (virtualOnsetEvent.getAai().containsKey(GENERIC_VNF_VNF_ID)) {
287 return virtualOnsetEvent.getAai().get(GENERIC_VNF_VNF_ID);
291 * If the vnf-name was retrieved from the onset then the vnf-id must be obtained from the event
292 * manager's A&AI GET query
296 if (Boolean.valueOf(PolicyEngineConstants.getManager().getEnvironmentProperty(AAI_CUSTOM_QUERY))) {
297 vnfId = this.aaiCqResponse.getDefaultGenericVnf().getVnfId();
299 vnfId = this.eventManager.getVnfResponse().getVnfId();
302 throw new AaiException("No vnf-id found");
306 } catch (AaiException e) {
307 throw new ControlLoopException(e.getMessage(), e);
310 throw new ControlLoopException("Target does not match target type");
313 private String getPnfTarget() throws ControlLoopException {
314 VirtualControlLoopEvent virtualOnsetEvent = (VirtualControlLoopEvent) this.onset;
315 if (!PNF_NAME.equalsIgnoreCase(onset.getTarget())) {
316 throw new ControlLoopException(
317 "Target in the onset event is either null or does not match target key expected in AAI section.");
319 return virtualOnsetEvent.getAai().get(PNF_NAME);
323 * Start an operation.
325 * @param onset the onset event
326 * @return the operation request
327 * @throws ControlLoopException if an error occurs
329 public Object startOperation(/* VirtualControlLoopEvent */ControlLoopEvent onset)
330 throws ControlLoopException {
331 verifyOperatonCanRun();
336 this.policyResult = null;
337 Operation operation = new Operation();
338 operation.attempt = ++this.attempts;
339 operation.clOperation.setActor(this.policy.getActor());
340 operation.clOperation.setOperation(this.policy.getRecipe());
341 operation.clOperation.setTarget(this.policy.getTarget().toString());
342 operation.clOperation.setSubRequestId(Integer.toString(operation.attempt));
344 // Now determine which actor we need to construct a request for
347 switch (policy.getActor()) {
349 return startAppcOperation(onset, operation);
351 return startSoOperation(onset, operation);
353 return startVfcOperation(onset, operation);
355 return startSdnrOperation(onset, operation);
357 return startSdncOperation(onset, operation);
359 return startCdsOperation(onset, operation);
361 throw new ControlLoopException("invalid actor " + policy.getActor() + " on policy");
364 } catch (AaiException e) {
365 throw new ControlLoopException(e.getMessage(), e);
370 private Object startAppcOperation(ControlLoopEvent onset, Operation operation) {
372 * If the recipe is ModifyConfig, a legacy APPC request is constructed. Otherwise an LCMRequest is
375 this.currentOperation = operation;
376 if ("ModifyConfig".equalsIgnoreCase(policy.getRecipe())) {
377 this.operationRequest = AppcActorServiceProvider.constructRequest((VirtualControlLoopEvent) onset,
378 operation.clOperation, this.policy, this.targetEntity);
380 this.operationRequest = AppcLcmActorServiceProvider.constructRequest(
381 (VirtualControlLoopEvent) onset, operation.clOperation, this.policy, this.targetEntity);
384 // Save the operation
387 return operationRequest;
391 private Object startSoOperation(ControlLoopEvent onset, Operation operation) {
392 SoActorServiceProvider soActorSp = new SoActorServiceProvider();
393 if (Boolean.valueOf(PolicyEngineConstants.getManager().getEnvironmentProperty(AAI_CUSTOM_QUERY))) {
394 this.operationRequest =
395 soActorSp.constructRequestCq((VirtualControlLoopEvent) onset, operation.clOperation,
396 this.policy, this.aaiCqResponse);
398 this.operationRequest = soActorSp.constructRequest((VirtualControlLoopEvent) onset,
399 operation.clOperation, this.policy, eventManager.getNqVserverFromAai());
402 // Save the operation
403 this.currentOperation = operation;
405 if (this.operationRequest == null) {
406 this.policyResult = PolicyResult.FAILURE;
409 return operationRequest;
413 private Object startVfcOperation(ControlLoopEvent onset, Operation operation) {
414 if (Boolean.valueOf(PolicyEngineConstants.getManager().getEnvironmentProperty(AAI_CUSTOM_QUERY))) {
415 this.operationRequest = VfcActorServiceProvider.constructRequestCq((VirtualControlLoopEvent) onset,
416 operation.clOperation, this.policy, this.aaiCqResponse);
418 this.operationRequest = VfcActorServiceProvider.constructRequest((VirtualControlLoopEvent) onset,
419 operation.clOperation, this.policy, this.eventManager.getVnfResponse(),
420 PolicyEngineConstants.getManager().getEnvironmentProperty("vfc.url"),
421 PolicyEngineConstants.getManager().getEnvironmentProperty("vfc.username"),
422 PolicyEngineConstants.getManager().getEnvironmentProperty("vfc.password"));
424 this.currentOperation = operation;
425 if (this.operationRequest == null) {
426 this.policyResult = PolicyResult.FAILURE;
428 return operationRequest;
432 private Object startSdnrOperation(ControlLoopEvent onset, Operation operation) {
434 * If the recipe is ModifyConfig or ModifyConfigANR, a SDNR request is constructed.
436 this.currentOperation = operation;
437 this.operationRequest = SdnrActorServiceProvider.constructRequest((VirtualControlLoopEvent) onset,
438 operation.clOperation, this.policy);
440 // Save the operation
442 if (this.operationRequest == null) {
443 this.policyResult = PolicyResult.FAILURE;
446 return operationRequest;
450 private Object startSdncOperation(ControlLoopEvent onset, Operation operation) {
451 SdncActorServiceProvider provider = new SdncActorServiceProvider();
452 this.operationRequest =
453 provider.constructRequest((VirtualControlLoopEvent) onset, operation.clOperation, this.policy);
454 this.currentOperation = operation;
455 if (this.operationRequest == null) {
456 this.policyResult = PolicyResult.FAILURE;
458 return operationRequest;
461 private Object startCdsOperation(ControlLoopEvent onset, Operation operation) throws AaiException {
463 CdsActorServiceProvider provider = new CdsActorServiceProvider();
464 Optional<ExecutionServiceInput> optionalRequest = provider.constructRequest(
465 (VirtualControlLoopEvent) onset, operation.clOperation, this.policy, this.buildAaiParams());
467 this.currentOperation = operation;
468 if (optionalRequest.isPresent()) {
469 this.operationRequest = optionalRequest.get();
471 this.operationRequest = null;
472 this.policyResult = PolicyResult.FAILURE;
475 return this.operationRequest;
479 * Build AAI parameters for CDS operation.
480 * @return a map containing vnf id key and value for the vnf to apply the action to.
481 * @throws AaiException if the vnf can not be found.
483 private Map<String, String> buildAaiParams() throws AaiException {
485 Map<String, String> result = new HashMap<>();
487 if (TargetType.VNF.equals(policy.getTarget().getType())
488 || TargetType.VFMODULE.equals(policy.getTarget().getType())) {
490 if (Boolean.valueOf(PolicyEngineConstants.getManager().getEnvironmentProperty(AAI_CUSTOM_QUERY))) {
492 ServiceInstance serviceInstance = this.aaiCqResponse.getServiceInstance();
493 if (serviceInstance == null) {
494 logger.info("Target entity service instance could not be found");
495 throw new AaiException("Target service instance could not be found");
498 GenericVnf genericVnf =
499 this.aaiCqResponse.getGenericVnfByModelInvariantId(policy.getTarget().getResourceID());
500 if (genericVnf == null) {
501 logger.info("Target entity generic vnf could not be found");
502 throw new AaiException("Target generic vnf could not be found");
505 result.put(AAI_SERVICE_INSTANCE_ID_KEY, serviceInstance.getServiceInstanceId());
506 result.put(GENERIC_VNF_VNF_ID, genericVnf.getVnfId());
508 } else if (TargetType.PNF.equals(policy.getTarget().getType())) {
509 result = this.eventManager.getPnf((VirtualControlLoopEvent) onset);
519 * @param response the response
520 * @return a PolicyResult
522 public PolicyResult onResponse(Object response) {
524 // Which response is it?
526 if (response instanceof Response) {
528 // Cast APPC response and handle it
530 return onResponse((Response) response);
531 } else if (response instanceof AppcLcmDmaapWrapper) {
533 // Cast LCM response and handle it
535 return onResponse(( AppcLcmDmaapWrapper) response);
536 } else if (response instanceof PciResponseWrapper) {
538 // Cast SDNR response and handle it
540 return onResponse((PciResponseWrapper) response);
541 } else if (response instanceof SoResponseWrapper) {
543 // Cast SO response and handle it
545 return onResponse((SoResponseWrapper) response);
546 } else if (response instanceof VfcResponse) {
548 // Cast VFC response and handle it
550 return onResponse((VfcResponse) response);
551 } else if (response instanceof SdncResponse) {
553 // Cast SDNC response and handle it
555 return onResponse((SdncResponse) response);
556 } else if (response instanceof CdsResponse) {
558 // Cast CDS response and handle it
560 return onResponse((CdsResponse) response);
567 * This method handles operation responses from APPC.
569 * @param appcResponse the APPC response
570 * @return The result of the response handling
572 private PolicyResult onResponse(Response appcResponse) {
574 // Determine which subrequestID (ie. attempt)
576 Integer operationAttempt = getSubRequestId(appcResponse);
577 if (operationAttempt == null) {
578 this.completeOperation(operationAttempt, "Policy was unable to parse APP-C SubRequestID (it was null).",
579 PolicyResult.FAILURE_EXCEPTION);
580 return PolicyResult.FAILURE_EXCEPTION;
583 // Sanity check the response message
585 if (appcResponse.getStatus() == null) {
587 // We cannot tell what happened if this doesn't exist
589 this.completeOperation(operationAttempt,
590 "Policy was unable to parse APP-C response status field (it was null).",
591 PolicyResult.FAILURE_EXCEPTION);
592 return PolicyResult.FAILURE_EXCEPTION;
595 // Get the Response Code
597 ResponseCode code = ResponseCode.toResponseCode(appcResponse.getStatus().getCode());
600 // We are unaware of this code
602 this.completeOperation(operationAttempt, "Policy was unable to parse APP-C response status code field.",
603 PolicyResult.FAILURE_EXCEPTION);
604 return PolicyResult.FAILURE_EXCEPTION;
607 return onResponse(appcResponse, operationAttempt, code);
611 private PolicyResult onResponse(Response appcResponse, Integer operationAttempt, ResponseCode code) {
613 // Ok, let's figure out what APP-C's response is
618 // This is good, they got our original message and
621 // Is there any need to track this?
627 // We'll consider these two codes as exceptions
629 this.completeOperation(operationAttempt, appcResponse.getStatus().getDescription(),
630 PolicyResult.FAILURE_EXCEPTION);
631 return getTimeoutResult(PolicyResult.FAILURE_EXCEPTION);
636 this.completeOperation(operationAttempt, appcResponse.getStatus().getDescription(),
637 PolicyResult.SUCCESS);
638 return getTimeoutResult(PolicyResult.SUCCESS);
643 this.completeOperation(operationAttempt, appcResponse.getStatus().getDescription(),
644 PolicyResult.FAILURE);
645 return getTimeoutResult(PolicyResult.FAILURE);
652 * This method handles operation responses from LCM.
654 * @param dmaapResponse the LCM response
655 * @return The result of the response handling
657 private PolicyResult onResponse(AppcLcmDmaapWrapper dmaapResponse) {
659 * Parse out the operation attempt using the subrequestid
661 Integer operationAttempt = AppcLcmActorServiceProvider
662 .parseOperationAttempt(dmaapResponse.getBody().getOutput().getCommonHeader().getSubRequestId());
663 if (operationAttempt == null) {
664 this.completeOperation(operationAttempt, "Policy was unable to parse APP-C SubRequestID (it was null).",
665 PolicyResult.FAILURE_EXCEPTION);
666 return PolicyResult.FAILURE_EXCEPTION;
670 * Process the APPCLCM response to see what PolicyResult should be returned
672 AbstractMap.SimpleEntry<PolicyResult, String> result =
673 AppcLcmActorServiceProvider.processResponse(dmaapResponse);
675 if (result.getKey() != null) {
676 this.completeOperation(operationAttempt, result.getValue(), result.getKey());
677 if (PolicyResult.FAILURE_TIMEOUT.equals(this.policyResult)) {
680 return result.getKey();
686 * This method handles operation responses from SDNR.
688 * @param dmaapResponse the SDNR response
689 * @return the result of the response handling
691 private PolicyResult onResponse(PciResponseWrapper dmaapResponse) {
693 * Parse out the operation attempt using the subrequestid
695 Integer operationAttempt = SdnrActorServiceProvider
696 .parseOperationAttempt(dmaapResponse.getBody().getCommonHeader().getSubRequestId());
697 if (operationAttempt == null) {
698 this.completeOperation(operationAttempt, "Policy was unable to parse SDNR SubRequestID.",
699 PolicyResult.FAILURE_EXCEPTION);
700 return PolicyResult.FAILURE_EXCEPTION;
704 * Process the SDNR response to see what PolicyResult should be returned
706 SdnrActorServiceProvider.Pair<PolicyResult, String> result =
707 SdnrActorServiceProvider.processResponse(dmaapResponse);
709 if (result.getResult() != null) {
710 this.completeOperation(operationAttempt, result.getMessage(), result.getResult());
711 if (PolicyResult.FAILURE_TIMEOUT.equals(this.policyResult)) {
714 return result.getResult();
720 * This method handles operation responses from SO.
722 * @param msoResponse the SO response
723 * @return The result of the response handling
725 private PolicyResult onResponse(SoResponseWrapper msoResponse) {
726 switch (msoResponse.getSoResponse().getHttpResponseCode()) {
730 // Consider it as success
732 this.completeOperation(this.attempts, msoResponse.getSoResponse().getHttpResponseCode() + SUCCESS_MSG,
733 PolicyResult.SUCCESS);
734 return getTimeoutResult(PolicyResult.SUCCESS);
737 // Consider it as failure
739 this.completeOperation(this.attempts, msoResponse.getSoResponse().getHttpResponseCode() + FAILED_MSG,
740 PolicyResult.FAILURE);
741 return getTimeoutResult(PolicyResult.FAILURE);
746 * This method handles operation responses from VFC.
748 * @param vfcResponse the VFC response
749 * @return The result of the response handling
751 private PolicyResult onResponse(VfcResponse vfcResponse) {
752 if ("finished".equalsIgnoreCase(vfcResponse.getResponseDescriptor().getStatus())) {
754 // Consider it as success
756 this.completeOperation(this.attempts, SUCCESS_MSG, PolicyResult.SUCCESS);
757 return getTimeoutResult(PolicyResult.SUCCESS);
760 // Consider it as failure
762 this.completeOperation(this.attempts, FAILED_MSG, PolicyResult.FAILURE);
763 if (PolicyResult.FAILURE_TIMEOUT.equals(this.policyResult)) {
766 // increment operation attempts for retries
768 return PolicyResult.FAILURE;
773 * This method handles operation responses from SDNC.
775 * @param sdncResponse the VFC response
776 * @return The result of the response handling
778 private PolicyResult onResponse(SdncResponse sdncResponse) {
779 if ("200".equals(sdncResponse.getResponseOutput().getResponseCode())) {
781 // Consider it as success
783 this.completeOperation(this.attempts, SUCCESS_MSG, PolicyResult.SUCCESS);
784 return getTimeoutResult(PolicyResult.SUCCESS);
787 // Consider it as failure
789 this.completeOperation(this.attempts, FAILED_MSG, PolicyResult.FAILURE);
790 if (PolicyResult.FAILURE_TIMEOUT.equals(this.policyResult)) {
793 // increment operation attempts for retries
795 return PolicyResult.FAILURE;
800 * This method handles operation responses from CDS.
802 * @param response the CDS response
803 * @return The result of the response handling
805 private PolicyResult onResponse(CdsResponse response) {
806 if (response != null && CdsActorConstants.SUCCESS.equals(response.getStatus())) {
808 // Consider it as success
810 this.completeOperation(this.attempts, SUCCESS_MSG, PolicyResult.SUCCESS);
811 return getTimeoutResult(PolicyResult.SUCCESS);
814 // Consider it as failure
816 this.completeOperation(this.attempts, FAILED_MSG, PolicyResult.FAILURE);
817 if (PolicyResult.FAILURE_TIMEOUT.equals(this.policyResult)) {
820 // increment operation attempts for retries
822 return PolicyResult.FAILURE;
826 private PolicyResult getTimeoutResult(PolicyResult result) {
827 return (PolicyResult.FAILURE_TIMEOUT.equals(this.policyResult) ? null : result);
831 private Integer getSubRequestId(Response appcResponse) {
833 return Integer.valueOf(appcResponse.getCommonHeader().getSubRequestId());
834 } catch (NumberFormatException e) {
836 // We cannot tell what happened if this doesn't exist
843 * Get the operation timeout.
845 * @return the timeout
847 public Integer getOperationTimeout() {
851 if (this.policy == null) {
852 logger.debug("getOperationTimeout returning 0");
855 logger.debug("getOperationTimeout returning {}", this.policy.getTimeout());
856 return this.policy.getTimeout();
860 * Get the operation timeout as a String.
862 * @param defaultTimeout the default timeout
863 * @return the timeout as a String
865 public String getOperationTimeoutString(int defaultTimeout) {
866 Integer to = this.getOperationTimeout();
867 if (to == null || to == 0) {
868 return Integer.toString(defaultTimeout) + "s";
870 return to.toString() + "s";
873 public PolicyResult getOperationResult() {
874 return this.policyResult;
878 * Get the operation as a message.
880 * @return the operation as a message
882 public String getOperationMessage() {
883 if (this.currentOperation != null && this.currentOperation.clOperation != null) {
884 return this.currentOperation.clOperation.toMessage();
887 if (!this.operationHistory.isEmpty()) {
888 return this.operationHistory.getLast().clOperation.toMessage();
894 * Get the operation as a message including the guard result.
896 * @param guardResult the guard result
897 * @return the operation as a message including the guard result
899 public String getOperationMessage(String guardResult) {
900 if (this.currentOperation != null && this.currentOperation.clOperation != null) {
901 return this.currentOperation.clOperation.toMessage() + ", Guard result: " + guardResult;
904 if (!this.operationHistory.isEmpty()) {
905 return this.operationHistory.getLast().clOperation.toMessage() + ", Guard result: " + guardResult;
911 * Get the operation history.
913 * @return the operation history
915 public String getOperationHistory() {
916 if (this.currentOperation != null && this.currentOperation.clOperation != null) {
917 return this.currentOperation.clOperation.toHistory();
920 if (!this.operationHistory.isEmpty()) {
921 return this.operationHistory.getLast().clOperation.toHistory();
929 * @return the list of control loop operations
931 public List<ControlLoopOperation> getHistory() {
932 LinkedList<ControlLoopOperation> history = new LinkedList<>();
933 for (Operation op : this.operationHistory) {
934 history.add(new ControlLoopOperation(op.clOperation));
941 * Set the operation has timed out.
943 public void setOperationHasTimedOut() {
947 this.completeOperation(this.attempts, "Operation timed out", PolicyResult.FAILURE_TIMEOUT);
951 * Set the operation has been denied by guard.
953 public void setOperationHasGuardDeny() {
957 this.completeOperation(this.attempts, "Operation denied by Guard", PolicyResult.FAILURE_GUARD);
960 public void setOperationHasException(String message) {
961 this.completeOperation(this.attempts, message, PolicyResult.FAILURE_EXCEPTION);
965 * Is the operation complete.
967 * @return <code>true</code> if the operation is complete, <code>false</code> otherwise
969 public boolean isOperationComplete() {
971 // Is there currently a result?
973 if (this.policyResult == null) {
975 // either we are in process or we
981 // We have some result, check if the operation failed
983 if (this.policyResult.equals(PolicyResult.FAILURE)) {
985 // Check if there were no retries specified
987 if (getMaxRetries() < 1) {
989 // The result is the failure
996 if (this.attempts > getMaxRetries()) {
998 // No more attempts allowed, reset
999 // that our actual result is failure due to retries
1001 this.policyResult = PolicyResult.FAILURE_RETRIES;
1005 // There are more attempts available to try the
1012 // Other results mean we are done
1017 public boolean isOperationRunning() {
1018 return (this.currentOperation != null);
1022 * This method verifies that the operation manager may run an operation.
1024 * @return True if the operation can run, false otherwise
1025 * @throws ControlLoopException if the operation cannot run
1027 private void verifyOperatonCanRun() throws ControlLoopException {
1029 // They shouldn't call us if we currently running something
1031 if (this.currentOperation != null) {
1033 // what do we do if we are already running an operation?
1035 throw new ControlLoopException("current operation is not null (an operation is already running)");
1038 // Check if we have maxed out on retries
1040 if (getMaxRetries() < 1) {
1042 // No retries are allowed, so check have we even made
1043 // one attempt to execute the operation?
1045 if (this.attempts >= 1) {
1047 // We have, let's ensure our PolicyResult is set
1049 if (this.policyResult == null) {
1050 this.policyResult = PolicyResult.FAILURE_RETRIES;
1055 throw new ControlLoopException("current operation failed and retries are not allowed");
1059 // Have we maxed out on retries?
1061 if (this.attempts > getMaxRetries()) {
1062 if (this.policyResult == null) {
1063 this.policyResult = PolicyResult.FAILURE_RETRIES;
1065 throw new ControlLoopException("current oepration has failed after " + this.attempts + " retries");
1071 * Gets the maximum number of retries.
1073 * @return the maximum number of retries, or {@code 0}, if not specified
1075 public int getMaxRetries() {
1076 return (policy.getRetry() != null ? policy.getRetry() : 0);
1079 private void storeOperationInDataBase() {
1080 // Only store in DB if enabled
1081 boolean guardEnabled = "false"
1082 .equalsIgnoreCase(PolicyEngineConstants.getManager().getEnvironmentProperty("guard.disabled"));
1083 if (!guardEnabled) {
1089 Properties props = new Properties();
1090 if (PolicyEngineConstants.getManager().getEnvironmentProperty(Util.ONAP_KEY_URL) != null
1091 && PolicyEngineConstants.getManager().getEnvironmentProperty(Util.ONAP_KEY_USER) != null
1092 && PolicyEngineConstants.getManager().getEnvironmentProperty(Util.ONAP_KEY_PASS) != null) {
1093 props.put(Util.ECLIPSE_LINK_KEY_URL,
1094 PolicyEngineConstants.getManager().getEnvironmentProperty(Util.ONAP_KEY_URL));
1095 props.put(Util.ECLIPSE_LINK_KEY_USER,
1096 PolicyEngineConstants.getManager().getEnvironmentProperty(Util.ONAP_KEY_USER));
1097 props.put(Util.ECLIPSE_LINK_KEY_PASS,
1098 PolicyEngineConstants.getManager().getEnvironmentProperty(Util.ONAP_KEY_PASS));
1099 props.put(PersistenceUnitProperties.CLASSLOADER, ControlLoopOperationManager.class.getClassLoader());
1103 String opsHistPu = System.getProperty("OperationsHistoryPU");
1104 if (!"OperationsHistoryPUTest".equals(opsHistPu)) {
1105 opsHistPu = "OperationsHistoryPU";
1111 em = Persistence.createEntityManagerFactory(opsHistPu, props).createEntityManager();
1112 } catch (Exception e) {
1113 logger.error("storeOperationInDataBase threw: ", e);
1117 Dbao newEntry = new Dbao();
1119 newEntry.setClosedLoopName(this.onset.getClosedLoopControlName());
1120 newEntry.setRequestId(this.onset.getRequestId().toString());
1121 newEntry.setActor(this.currentOperation.clOperation.getActor());
1122 newEntry.setOperation(this.currentOperation.clOperation.getOperation());
1123 newEntry.setTarget(this.targetEntity);
1124 newEntry.setStarttime(Timestamp.from(this.currentOperation.clOperation.getStart()));
1125 newEntry.setSubrequestId(this.currentOperation.clOperation.getSubRequestId());
1126 newEntry.setEndtime(new Timestamp(this.currentOperation.clOperation.getEnd().toEpochMilli()));
1127 newEntry.setMessage(this.currentOperation.clOperation.getMessage());
1128 newEntry.setOutcome(this.currentOperation.clOperation.getOutcome());
1130 em.getTransaction().begin();
1131 em.persist(newEntry);
1132 em.getTransaction().commit();
1137 private void completeOperation(Integer attempt, String message, PolicyResult result) {
1138 if (attempt == null) {
1139 logger.debug("attempt cannot be null (i.e. subRequestID)");
1142 if (this.currentOperation != null) {
1143 if (this.currentOperation.attempt == attempt.intValue()) {
1144 this.currentOperation.clOperation.setEnd(Instant.now());
1145 this.currentOperation.clOperation.setMessage(message);
1146 this.currentOperation.clOperation.setOutcome(result.toString());
1147 this.currentOperation.policyResult = result;
1149 // Save it in history
1151 this.operationHistory.add(this.currentOperation);
1152 this.storeOperationInDataBase();
1154 // Set our last result
1156 this.policyResult = result;
1158 // Clear the current operation field
1160 this.currentOperation = null;
1163 logger.debug("not current");
1165 for (Operation op : this.operationHistory) {
1166 if (op.attempt == attempt.intValue()) {
1167 op.clOperation.setEnd(Instant.now());
1168 op.clOperation.setMessage(message);
1169 op.clOperation.setOutcome(result.toString());
1170 op.policyResult = result;
1174 logger.debug("Could not find associated operation");
1179 * Commit the abatement to the history database.
1181 * @param message the abatement message
1182 * @param outcome the abatement outcome
1184 public void commitAbatement(String message, String outcome) {
1185 logger.info("commitAbatement: {}. {}", message, outcome);
1187 if (this.currentOperation == null) {
1189 this.currentOperation = this.operationHistory.getLast();
1190 } catch (NoSuchElementException e) {
1191 logger.error("{}: commitAbatement threw an exception ", this, e);
1195 this.currentOperation.clOperation.setEnd(Instant.now());
1196 this.currentOperation.clOperation.setMessage(message);
1197 this.currentOperation.clOperation.setOutcome(outcome);
1199 // Store commit in DB
1201 this.storeOperationInDataBase();
1203 // Clear the current operation field
1205 this.currentOperation = null;
1209 * Construct a ControlLoopResponse object from actor response and input event.
1211 * @param response the response from actor
1212 * @param event the input event
1214 * @return a ControlLoopResponse
1216 public ControlLoopResponse getControlLoopResponse(Object response, VirtualControlLoopEvent event) {
1217 if (response instanceof PciResponseWrapper) {
1219 // Cast SDNR response and handle it
1221 return SdnrActorServiceProvider.getControlLoopResponse((PciResponseWrapper) response, event);