2 * ============LICENSE_START=======================================================
3 * controlloop event manager
4 * ================================================================================
5 * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.onap.policy.controlloop.eventmanager;
23 import java.io.Serializable;
24 import java.io.UnsupportedEncodingException;
25 import java.net.URLDecoder;
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.HashMap;
29 import java.util.LinkedList;
30 import java.util.List;
32 import java.util.NoSuchElementException;
33 import java.util.UUID;
34 import org.onap.policy.aai.AaiCqResponse;
35 import org.onap.policy.aai.AaiGetVnfResponse;
36 import org.onap.policy.aai.AaiGetVserverResponse;
37 import org.onap.policy.aai.AaiManager;
38 import org.onap.policy.aai.AaiNqInstanceFilters;
39 import org.onap.policy.aai.AaiNqNamedQuery;
40 import org.onap.policy.aai.AaiNqQueryParameters;
41 import org.onap.policy.aai.AaiNqRequest;
42 import org.onap.policy.aai.AaiNqResponse;
43 import org.onap.policy.aai.AaiNqResponseWrapper;
44 import org.onap.policy.aai.AaiNqVServer;
45 import org.onap.policy.aai.util.AaiException;
46 import org.onap.policy.controlloop.ControlLoopEventStatus;
47 import org.onap.policy.controlloop.ControlLoopException;
48 import org.onap.policy.controlloop.ControlLoopNotificationType;
49 import org.onap.policy.controlloop.ControlLoopOperation;
50 import org.onap.policy.controlloop.VirtualControlLoopEvent;
51 import org.onap.policy.controlloop.VirtualControlLoopNotification;
52 import org.onap.policy.controlloop.policy.FinalResult;
53 import org.onap.policy.controlloop.policy.Policy;
54 import org.onap.policy.controlloop.processor.ControlLoopProcessor;
55 import org.onap.policy.drools.system.PolicyEngine;
56 import org.onap.policy.guard.GuardResult;
57 import org.onap.policy.guard.LockCallback;
58 import org.onap.policy.guard.PolicyGuard;
59 import org.onap.policy.guard.PolicyGuard.LockResult;
60 import org.onap.policy.guard.TargetLock;
61 import org.onap.policy.rest.RestManager;
62 import org.onap.policy.so.util.Serialization;
63 import org.slf4j.Logger;
64 import org.slf4j.LoggerFactory;
66 public class ControlLoopEventManager implements LockCallback, Serializable {
67 public static final String PROV_STATUS_ACTIVE = "ACTIVE";
68 private static final String VM_NAME = "VM_NAME";
69 private static final String VNF_NAME = "VNF_NAME";
70 public static final String GENERIC_VNF_VNF_ID = "generic-vnf.vnf-id";
71 public static final String GENERIC_VNF_VNF_NAME = "generic-vnf.vnf-name";
72 public static final String VSERVER_VSERVER_NAME = "vserver.vserver-name";
73 public static final String GENERIC_VNF_IS_CLOSED_LOOP_DISABLED = "generic-vnf.is-closed-loop-disabled";
74 public static final String VSERVER_IS_CLOSED_LOOP_DISABLED = "vserver.is-closed-loop-disabled";
75 public static final String GENERIC_VNF_PROV_STATUS = "generic-vnf.prov-status";
76 public static final String VSERVER_PROV_STATUS = "vserver.prov-status";
78 private static final String AAI_URL = "aai.url";
79 private static final String AAI_USERNAME_PROPERTY = "aai.username";
80 private static final String AAI_PASS_PROPERTY = "aai.password";
82 private static final String QUERY_AAI_ERROR_MSG = "Exception from queryAai: ";
85 * Additional time, in seconds, to add to a "lock" request. This ensures that the lock won't expire right before an
86 * operation completes.
88 private static final int ADDITIONAL_LOCK_SEC = 60;
90 private static final Logger logger = LoggerFactory.getLogger(ControlLoopEventManager.class);
92 private static final long serialVersionUID = -1216568161322872641L;
93 public final String closedLoopControlName;
94 private final UUID requestId;
96 private String controlLoopResult;
97 private ControlLoopProcessor processor = null;
98 private VirtualControlLoopEvent onset;
99 private Integer numOnsets = 0;
100 private Integer numAbatements = 0;
101 private VirtualControlLoopEvent abatement;
102 private FinalResult controlLoopTimedOut = null;
104 private boolean isActivated = false;
105 private LinkedList<ControlLoopOperation> controlLoopHistory = new LinkedList<>();
106 private ControlLoopOperationManager currentOperation = null;
107 private ControlLoopOperationManager lastOperationManager = null;
108 private transient TargetLock targetLock = null;
109 private AaiGetVnfResponse vnfResponse = null;
110 private AaiGetVserverResponse vserverResponse = null;
111 private boolean useTargetLock = true;
114 * Wrapper for AAI vserver named-query response. This is initialized in a lazy fashion.
116 private AaiNqResponseWrapper nqVserverResponse = null;
118 private static Collection<String> requiredAAIKeys = new ArrayList<>();
121 requiredAAIKeys.add("AICVServerSelfLink");
122 requiredAAIKeys.add("AICIdentity");
123 requiredAAIKeys.add("is_closed_loop_disabled");
124 requiredAAIKeys.add(VM_NAME);
127 public ControlLoopEventManager(String closedLoopControlName, UUID requestId) {
128 this.closedLoopControlName = closedLoopControlName;
129 this.requestId = requestId;
132 public String getClosedLoopControlName() {
133 return closedLoopControlName;
136 public String getControlLoopResult() {
137 return controlLoopResult;
140 public void setControlLoopResult(String controlLoopResult) {
141 this.controlLoopResult = controlLoopResult;
144 public Integer getNumOnsets() {
148 public void setNumOnsets(Integer numOnsets) {
149 this.numOnsets = numOnsets;
152 public Integer getNumAbatements() {
153 return numAbatements;
156 public void setNumAbatements(Integer numAbatements) {
157 this.numAbatements = numAbatements;
160 public boolean isActivated() {
164 public void setActivated(boolean isActivated) {
165 this.isActivated = isActivated;
168 public boolean useTargetLock() {
169 return useTargetLock();
172 public void setUseTargetLock(boolean useTargetLock) {
173 this.useTargetLock = useTargetLock;
176 public VirtualControlLoopEvent getOnsetEvent() {
180 public VirtualControlLoopEvent getAbatementEvent() {
181 return this.abatement;
184 public ControlLoopProcessor getProcessor() {
185 return this.processor;
188 public UUID getRequestId() {
193 * Activate a control loop event.
195 * @param event the event
196 * @return the VirtualControlLoopNotification
198 public VirtualControlLoopNotification activate(VirtualControlLoopEvent event) {
199 VirtualControlLoopNotification notification = new VirtualControlLoopNotification(event);
202 // This method should ONLY be called ONCE
204 if (this.isActivated) {
205 throw new ControlLoopException("ControlLoopEventManager has already been activated.");
208 // Syntax check the event
210 checkEventSyntax(event);
213 // At this point we are good to go with this event
218 notification.setNotification(ControlLoopNotificationType.ACTIVE);
220 // Set ourselves as active
222 this.isActivated = true;
223 } catch (ControlLoopException e) {
224 logger.error("{}: activate by event threw: ", this, e);
225 notification.setNotification(ControlLoopNotificationType.REJECTED);
226 notification.setMessage(e.getMessage());
232 * Activate a control loop event.
234 * @param yamlSpecification the yaml specification
235 * @param event the event
236 * @return the VirtualControlLoopNotification
238 public VirtualControlLoopNotification activate(String yamlSpecification, VirtualControlLoopEvent event) {
239 VirtualControlLoopNotification notification = new VirtualControlLoopNotification(event);
242 // This method should ONLY be called ONCE
244 if (this.isActivated) {
245 throw new ControlLoopException("ControlLoopEventManager has already been activated.");
248 // Syntax check the event
250 checkEventSyntax(event);
255 if (yamlSpecification == null || yamlSpecification.length() < 1) {
256 throw new ControlLoopException("yaml specification is null or 0 length");
258 } catch (ControlLoopException e) {
259 logger.error("{}: activate by YAML specification and event threw: ", this, e);
260 notification.setNotification(ControlLoopNotificationType.REJECTED);
261 notification.setMessage(e.getMessage());
265 String decodedYaml = null;
267 decodedYaml = URLDecoder.decode(yamlSpecification, "UTF-8");
268 if (decodedYaml != null && decodedYaml.length() > 0) {
269 yamlSpecification = decodedYaml;
271 } catch (UnsupportedEncodingException e) {
272 logger.error("{}: YAML decode in activate by YAML specification and event threw: ", this, e);
273 notification.setNotification(ControlLoopNotificationType.REJECTED);
274 notification.setMessage(e.getMessage());
280 // Parse the YAML specification
282 this.processor = new ControlLoopProcessor(yamlSpecification);
284 // At this point we are good to go with this event
291 notification.setNotification(ControlLoopNotificationType.ACTIVE);
293 // Set ourselves as active
295 this.isActivated = true;
296 } catch (ControlLoopException e) {
297 logger.error("{}: activate by YAML specification and event threw: ", this, e);
298 notification.setNotification(ControlLoopNotificationType.REJECTED);
299 notification.setMessage(e.getMessage());
305 * Check if the control loop is final.
307 * @return a VirtualControlLoopNotification if the control loop is final, otherwise <code>null</code> is returned
308 * @throws ControlLoopException if an error occurs
310 public VirtualControlLoopNotification isControlLoopFinal() throws ControlLoopException {
312 // Check if they activated us
314 if (!this.isActivated) {
315 throw new ControlLoopException("ControlLoopEventManager MUST be activated first.");
318 // Make sure we are expecting this call.
320 if (this.onset == null) {
321 throw new ControlLoopException("No onset event for ControlLoopEventManager.");
324 // Ok, start creating the notification
326 VirtualControlLoopNotification notification = new VirtualControlLoopNotification(this.onset);
328 // Check if the overall control loop has timed out
330 if (this.isControlLoopTimedOut()) {
332 // Yes we have timed out
334 notification.setNotification(ControlLoopNotificationType.FINAL_FAILURE);
335 notification.setMessage("Control Loop timed out");
336 notification.getHistory().addAll(this.controlLoopHistory);
340 // Check if the current policy is Final
342 FinalResult result = this.processor.checkIsCurrentPolicyFinal();
343 if (result == null) {
345 // we are not at a final result
351 case FINAL_FAILURE_EXCEPTION:
352 notification.setNotification(ControlLoopNotificationType.FINAL_FAILURE);
353 notification.setMessage("Exception in processing closed loop");
356 case FINAL_FAILURE_RETRIES:
357 case FINAL_FAILURE_TIMEOUT:
358 case FINAL_FAILURE_GUARD:
359 notification.setNotification(ControlLoopNotificationType.FINAL_FAILURE);
362 notification.setNotification(ControlLoopNotificationType.FINAL_OPENLOOP);
365 notification.setNotification(ControlLoopNotificationType.FINAL_SUCCESS);
371 // Be sure to add all the history
373 notification.getHistory().addAll(this.controlLoopHistory);
378 * Process the control loop.
380 * @return a ControlLoopOperationManager
381 * @throws ControlLoopException if an error occurs
382 * @throws AaiException if an error occurs retrieving information from A&AI
384 public ControlLoopOperationManager processControlLoop() throws ControlLoopException, AaiException {
386 // Check if they activated us
388 if (!this.isActivated) {
389 throw new ControlLoopException("ControlLoopEventManager MUST be activated first.");
392 // Make sure we are expecting this call.
394 if (this.onset == null) {
395 throw new ControlLoopException("No onset event for ControlLoopEventManager.");
398 // Is there a current operation?
400 if (this.currentOperation != null) {
402 // Throw an exception, or simply return the current operation?
404 throw new ControlLoopException("Already working an Operation, do not call this method.");
407 // Ensure we are not FINAL
409 VirtualControlLoopNotification notification = this.isControlLoopFinal();
410 if (notification != null) {
412 // This is weird, we require them to call the isControlLoopFinal() method first
414 // We should really abstract this and avoid throwing an exception, because it really
415 // isn't an exception.
417 throw new ControlLoopException("Control Loop is in FINAL state, do not call this method.");
420 // Not final so get the policy that needs to be worked on.
422 Policy policy = this.processor.getCurrentPolicy();
423 if (policy == null) {
424 throw new ControlLoopException("ControlLoopEventManager: processor came upon null Policy.");
427 // And setup an operation
429 this.lastOperationManager = this.currentOperation;
430 this.currentOperation = new ControlLoopOperationManager(this.onset, policy, this);
434 return this.currentOperation;
438 * Finish an operation.
440 * @param operation the operation
442 public void finishOperation(ControlLoopOperationManager operation) throws ControlLoopException {
444 // Verify we have a current operation
446 if (this.currentOperation != null) {
448 // Validate they are finishing the current operation
449 // PLD - this is simply comparing the policy. Do we want to equals the whole object?
451 if (this.currentOperation.policy.equals(operation.policy)) {
452 logger.debug("Finishing {} result is {}", this.currentOperation.policy.getRecipe(),
453 this.currentOperation.getOperationResult());
457 this.controlLoopHistory.addAll(this.currentOperation.getHistory());
459 // Move to the next Policy
461 this.processor.nextPolicyForResult(this.currentOperation.getOperationResult());
463 // Just null this out
465 this.lastOperationManager = this.currentOperation;
466 this.currentOperation = null;
468 // TODO: Release our lock
472 logger.debug("Cannot finish current operation {} does not match given operation {}",
473 this.currentOperation.policy, operation.policy);
476 throw new ControlLoopException("No operation to finish.");
480 * Obtain a lock for the current operation.
482 * @return the lock result
483 * @throws ControlLoopException if an error occurs
485 public synchronized LockResult<GuardResult, TargetLock> lockCurrentOperation() throws ControlLoopException {
489 if (this.currentOperation == null) {
490 throw new ControlLoopException("Do not have a current operation.");
493 // Not using target locks? Create and return a lock w/o actually locking.
495 if (!this.useTargetLock) {
496 TargetLock lock = PolicyGuard.createTargetLock(this.currentOperation.policy.getTarget().getType(),
497 this.currentOperation.getTargetEntity(), this.onset.getRequestId(), this);
498 this.targetLock = lock;
499 return LockResult.createLockResult(GuardResult.LOCK_ACQUIRED, lock);
502 // Have we acquired it already?
504 if (this.targetLock != null) {
506 // TODO: Make sure the current lock is for the same target.
507 // Currently, it should be. But in the future it may not.
509 GuardResult result = PolicyGuard.lockTarget(targetLock,
510 this.currentOperation.getOperationTimeout() + ADDITIONAL_LOCK_SEC);
511 return new LockResult<>(result, this.targetLock);
516 LockResult<GuardResult, TargetLock> lockResult = PolicyGuard.lockTarget(
517 this.currentOperation.policy.getTarget().getType(), this.currentOperation.getTargetEntity(),
518 this.onset.getRequestId(), this, this.currentOperation.getOperationTimeout() + ADDITIONAL_LOCK_SEC);
522 if (lockResult.getA().equals(GuardResult.LOCK_ACQUIRED)) {
524 // Yes, let's save it
526 this.targetLock = lockResult.getB();
533 * Release the lock for the current operation.
535 * @return the target lock
537 public synchronized TargetLock unlockCurrentOperation() {
538 if (this.targetLock == null) {
542 TargetLock returnLock = this.targetLock;
543 this.targetLock = null;
545 // if using target locking unlock before returning
547 if (this.useTargetLock) {
548 PolicyGuard.unlockTarget(returnLock);
551 // always return the old target lock so rules can retract it
555 public enum NewEventStatus {
556 FIRST_ONSET, SUBSEQUENT_ONSET, FIRST_ABATEMENT, SUBSEQUENT_ABATEMENT, SYNTAX_ERROR;
560 * An event onset/abatement.
562 * @param event the event
564 * @throws AaiException if an error occurs retrieving information from A&AI
566 public NewEventStatus onNewEvent(VirtualControlLoopEvent event) throws AaiException {
568 this.checkEventSyntax(event);
569 if (event.getClosedLoopEventStatus() == ControlLoopEventStatus.ONSET) {
571 // Check if this is our original ONSET
573 if (event.equals(this.onset)) {
575 // Query A&AI if needed
582 return NewEventStatus.FIRST_ONSET;
585 // Log that we got an onset
588 return NewEventStatus.SUBSEQUENT_ONSET;
589 } else if (event.getClosedLoopEventStatus() == ControlLoopEventStatus.ABATED) {
591 // Have we already got an abatement?
593 if (this.abatement == null) {
597 this.abatement = event;
599 // Keep track that we received another
601 this.numAbatements++;
605 return NewEventStatus.FIRST_ABATEMENT;
608 // Keep track that we received another
610 this.numAbatements++;
614 return NewEventStatus.SUBSEQUENT_ABATEMENT;
617 } catch (ControlLoopException e) {
618 logger.error("{}: onNewEvent threw: ", this, e);
620 return NewEventStatus.SYNTAX_ERROR;
625 * Commit the abatement to the history database.
627 * @param message the abatement message
628 * @param outcome the abatement outcome
630 public void commitAbatement(String message, String outcome) {
631 if (this.lastOperationManager == null) {
632 logger.error("{}: commitAbatement: no operation manager", this);
636 this.lastOperationManager.commitAbatement(message, outcome);
637 } catch (NoSuchElementException e) {
638 logger.error("{}: commitAbatement threw an exception ", this, e);
644 * Set the control loop time out.
646 * @return a VirtualControlLoopNotification
648 public VirtualControlLoopNotification setControlLoopTimedOut() {
649 this.controlLoopTimedOut = FinalResult.FINAL_FAILURE_TIMEOUT;
650 VirtualControlLoopNotification notification = new VirtualControlLoopNotification(this.onset);
651 notification.setNotification(ControlLoopNotificationType.FINAL_FAILURE);
652 notification.setMessage("Control Loop timed out");
653 notification.getHistory().addAll(this.controlLoopHistory);
657 public boolean isControlLoopTimedOut() {
658 return (this.controlLoopTimedOut == FinalResult.FINAL_FAILURE_TIMEOUT);
662 * Get the control loop timeout.
664 * @param defaultTimeout the default timeout
665 * @return the timeout
667 public int getControlLoopTimeout(Integer defaultTimeout) {
668 if (this.processor != null && this.processor.getControlLoop() != null) {
669 Integer timeout = this.processor.getControlLoop().getTimeout();
670 if (timeout != null && timeout > 0) {
674 if (defaultTimeout != null) {
675 return defaultTimeout;
680 public AaiGetVnfResponse getVnfResponse() {
684 public AaiGetVserverResponse getVserverResponse() {
685 return vserverResponse;
689 * Check an event syntax.
691 * @param event the event syntax
692 * @throws ControlLoopException if an error occurs
694 public void checkEventSyntax(VirtualControlLoopEvent event) throws ControlLoopException {
695 if (event.getClosedLoopEventStatus() == null
696 || (event.getClosedLoopEventStatus() != ControlLoopEventStatus.ONSET
697 && event.getClosedLoopEventStatus() != ControlLoopEventStatus.ABATED)) {
698 throw new ControlLoopException("Invalid value in closedLoopEventStatus");
700 if (event.getClosedLoopControlName() == null || event.getClosedLoopControlName().length() < 1) {
701 throw new ControlLoopException("No control loop name");
703 if (event.getRequestId() == null) {
704 throw new ControlLoopException("No request ID");
706 if (event.getClosedLoopEventStatus() == ControlLoopEventStatus.ABATED) {
709 if (event.getTarget() == null || event.getTarget().length() < 1) {
710 throw new ControlLoopException("No target field");
711 } else if (!VM_NAME.equalsIgnoreCase(event.getTarget()) && !VNF_NAME.equalsIgnoreCase(event.getTarget())
712 && !VSERVER_VSERVER_NAME.equalsIgnoreCase(event.getTarget())
713 && !GENERIC_VNF_VNF_ID.equalsIgnoreCase(event.getTarget())
714 && !GENERIC_VNF_VNF_NAME.equalsIgnoreCase(event.getTarget())) {
715 throw new ControlLoopException("target field invalid - expecting VM_NAME or VNF_NAME");
717 if (event.getAai() == null) {
718 throw new ControlLoopException("AAI is null");
720 if (event.getAai().get(GENERIC_VNF_VNF_ID) == null && event.getAai().get(VSERVER_VSERVER_NAME) == null
721 && event.getAai().get(GENERIC_VNF_VNF_NAME) == null) {
722 throw new ControlLoopException(
723 "generic-vnf.vnf-id or generic-vnf.vnf-name or vserver.vserver-name information missing");
728 * Query A&AI for an event.
730 * @param event the event
731 * @throws AaiException if an error occurs retrieving information from A&AI
733 public void queryAai(VirtualControlLoopEvent event) throws AaiException {
735 Map<String, String> aai = event.getAai();
737 if (aai.containsKey(VSERVER_IS_CLOSED_LOOP_DISABLED) || aai.containsKey(GENERIC_VNF_IS_CLOSED_LOOP_DISABLED)) {
739 if (isClosedLoopDisabled(event)) {
740 throw new AaiException("is-closed-loop-disabled is set to true on VServer or VNF");
743 if (isProvStatusInactive(event)) {
744 throw new AaiException("prov-status is not ACTIVE on VServer or VNF");
747 // no need to query, as we already have the data
751 if (vnfResponse != null || vserverResponse != null) {
752 // query has already been performed
757 if (aai.containsKey(GENERIC_VNF_VNF_ID) || aai.containsKey(GENERIC_VNF_VNF_NAME)) {
758 vnfResponse = getAaiVnfInfo(event);
759 processVnfResponse(vnfResponse, aai.containsKey(GENERIC_VNF_VNF_ID));
760 } else if (aai.containsKey(VSERVER_VSERVER_NAME)) {
761 vserverResponse = getAaiVserverInfo(event);
762 processVServerResponse(vserverResponse);
764 } catch (AaiException e) {
765 logger.error(QUERY_AAI_ERROR_MSG, e);
767 } catch (Exception e) {
768 logger.error(QUERY_AAI_ERROR_MSG, e);
769 throw new AaiException(QUERY_AAI_ERROR_MSG + e.toString());
774 * Process a response from A&AI for a VNF.
776 * @param aaiResponse the response from A&AI
777 * @param queryByVnfId <code>true</code> if the query was based on vnf-id, <code>false</code> if the query was based
779 * @throws AaiException if an error occurs processing the response
781 private static void processVnfResponse(AaiGetVnfResponse aaiResponse, boolean queryByVnfId) throws AaiException {
782 String queryTypeString = (queryByVnfId ? "vnf-id" : "vnf-name");
784 if (aaiResponse == null) {
785 throw new AaiException("AAI Response is null (query by " + queryTypeString + ")");
787 if (aaiResponse.getRequestError() != null) {
788 throw new AaiException("AAI Responded with a request error (query by " + queryTypeString + ")");
791 if (aaiResponse.getIsClosedLoopDisabled()) {
792 throw new AaiException("is-closed-loop-disabled is set to true (query by " + queryTypeString + ")");
795 if (!PROV_STATUS_ACTIVE.equals(aaiResponse.getProvStatus())) {
796 throw new AaiException("prov-status is not ACTIVE (query by " + queryTypeString + ")");
801 * Process a response from A&AI for a VServer.
803 * @param aaiResponse the response from A&AI
804 * @throws AaiException if an error occurs processing the response
806 private static void processVServerResponse(AaiGetVserverResponse aaiResponse) throws AaiException {
807 if (aaiResponse == null) {
808 throw new AaiException("AAI Response is null (query by vserver-name)");
810 if (aaiResponse.getRequestError() != null) {
811 throw new AaiException("AAI Responded with a request error (query by vserver-name)");
814 List<AaiNqVServer> lst = aaiResponse.getVserver();
819 AaiNqVServer svr = lst.get(0);
820 if (svr.getIsClosedLoopDisabled()) {
821 throw new AaiException("is-closed-loop-disabled is set to true (query by vserver-name)");
824 if (!PROV_STATUS_ACTIVE.equals(svr.getProvStatus())) {
825 throw new AaiException("prov-status is not ACTIVE (query by vserver-name)");
830 * Is closed loop disabled for an event.
832 * @param event the event
833 * @return <code>true</code> if the control loop is disabled, <code>false</code> otherwise
835 public static boolean isClosedLoopDisabled(VirtualControlLoopEvent event) {
836 Map<String, String> aai = event.getAai();
837 return (isAaiTrue(aai.get(VSERVER_IS_CLOSED_LOOP_DISABLED))
838 || isAaiTrue(aai.get(GENERIC_VNF_IS_CLOSED_LOOP_DISABLED)));
842 * Does provisioning status, for an event, have a value other than ACTIVE.
844 * @param event the event
845 * @return {@code true} if the provisioning status is neither ACTIVE nor {@code null}, {@code false} otherwise
847 protected static boolean isProvStatusInactive(VirtualControlLoopEvent event) {
848 Map<String, String> aai = event.getAai();
849 return (!PROV_STATUS_ACTIVE.equals(aai.getOrDefault(VSERVER_PROV_STATUS, PROV_STATUS_ACTIVE))
850 || !PROV_STATUS_ACTIVE.equals(aai.getOrDefault(GENERIC_VNF_PROV_STATUS, PROV_STATUS_ACTIVE)));
854 * Determines the boolean value represented by the given AAI field value.
856 * @param aaiValue value to be examined
857 * @return the boolean value represented by the field value, or {@code false} if the value is {@code null}
859 protected static boolean isAaiTrue(String aaiValue) {
860 return ("true".equalsIgnoreCase(aaiValue) || "T".equalsIgnoreCase(aaiValue) || "yes".equalsIgnoreCase(aaiValue)
861 || "Y".equalsIgnoreCase(aaiValue));
865 * Get the A&AI VService information for an event.
867 * @param event the event
868 * @return a AaiGetVserverResponse
869 * @throws ControlLoopException if an error occurs
871 public static AaiGetVserverResponse getAaiVserverInfo(VirtualControlLoopEvent event) throws ControlLoopException {
872 UUID requestId = event.getRequestId();
873 AaiGetVserverResponse response = null;
874 String vserverName = event.getAai().get(VSERVER_VSERVER_NAME);
877 if (vserverName != null) {
878 String aaiHostUrl = PolicyEngine.manager.getEnvironmentProperty(AAI_URL);
879 String aaiUser = PolicyEngine.manager.getEnvironmentProperty(AAI_USERNAME_PROPERTY);
880 String aaiPassword = PolicyEngine.manager.getEnvironmentProperty(AAI_PASS_PROPERTY);
881 String aaiGetQueryByVserver = "/aai/v11/nodes/vservers?vserver-name=";
882 String url = aaiHostUrl + aaiGetQueryByVserver;
883 logger.info("AAI Host URL by VServer: {}", url);
884 response = new AaiManager(new RestManager()).getQueryByVserverName(url, aaiUser, aaiPassword, requestId,
887 } catch (Exception e) {
888 logger.error("getAaiVserverInfo exception: ", e);
889 throw new ControlLoopException("Exception in getAaiVserverInfo: ", e);
896 * Get A&AI VNF information for an event.
898 * @param event the event
899 * @return a AaiGetVnfResponse
900 * @throws ControlLoopException if an error occurs
902 public static AaiGetVnfResponse getAaiVnfInfo(VirtualControlLoopEvent event) throws ControlLoopException {
903 UUID requestId = event.getRequestId();
904 AaiGetVnfResponse response = null;
905 String vnfName = event.getAai().get(GENERIC_VNF_VNF_NAME);
906 String vnfId = event.getAai().get(GENERIC_VNF_VNF_ID);
908 String aaiHostUrl = PolicyEngine.manager.getEnvironmentProperty(AAI_URL);
909 String aaiUser = PolicyEngine.manager.getEnvironmentProperty(AAI_USERNAME_PROPERTY);
910 String aaiPassword = PolicyEngine.manager.getEnvironmentProperty(AAI_PASS_PROPERTY);
913 if (vnfName != null) {
914 String aaiGetQueryByVnfName = "/aai/v11/network/generic-vnfs/generic-vnf?vnf-name=";
915 String url = aaiHostUrl + aaiGetQueryByVnfName;
916 logger.info("AAI Host URL by VNF name: {}", url);
917 response = new AaiManager(new RestManager()).getQueryByVnfName(url, aaiUser, aaiPassword, requestId,
919 } else if (vnfId != null) {
920 String aaiGetQueryByVnfId = "/aai/v11/network/generic-vnfs/generic-vnf/";
921 String url = aaiHostUrl + aaiGetQueryByVnfId;
922 logger.info("AAI Host URL by VNF ID: {}", url);
924 new AaiManager(new RestManager()).getQueryByVnfId(url, aaiUser, aaiPassword, requestId, vnfId);
926 } catch (Exception e) {
927 logger.error("getAaiVnfInfo exception: ", e);
928 throw new ControlLoopException("Exception in getAaiVnfInfo: ", e);
935 * Gets the output from the AAI vserver named-query, using the cache, if appropriate.
937 * @return output from the AAI vserver named-query
939 public AaiNqResponseWrapper getNqVserverFromAai() {
940 if (nqVserverResponse != null) {
942 return nqVserverResponse;
945 String vserverName = onset.getAai().get(VSERVER_VSERVER_NAME);
946 if (vserverName == null) {
947 logger.warn("Missing vserver-name for AAI request {}", onset.getRequestId());
951 // create AAI named-query request with UUID started with ""
952 AaiNqRequest aaiNqRequest = new AaiNqRequest();
953 AaiNqQueryParameters aaiNqQueryParam = new AaiNqQueryParameters();
954 AaiNqNamedQuery aaiNqNamedQuery = new AaiNqNamedQuery();
955 final AaiNqInstanceFilters aaiNqInstanceFilter = new AaiNqInstanceFilters();
958 aaiNqNamedQuery.setNamedQueryUuid(UUID.fromString("4ff56a54-9e3f-46b7-a337-07a1d3c6b469"));
959 aaiNqQueryParam.setNamedQuery(aaiNqNamedQuery);
960 aaiNqRequest.setQueryParameters(aaiNqQueryParam);
964 Map<String, Map<String, String>> aaiNqInstanceFilterMap = new HashMap<>();
965 Map<String, String> aaiNqInstanceFilterMapItem = new HashMap<>();
966 aaiNqInstanceFilterMapItem.put("vserver-name", vserverName);
967 aaiNqInstanceFilterMap.put("vserver", aaiNqInstanceFilterMapItem);
968 aaiNqInstanceFilter.getInstanceFilter().add(aaiNqInstanceFilterMap);
969 aaiNqRequest.setInstanceFilters(aaiNqInstanceFilter);
971 if (logger.isDebugEnabled()) {
972 logger.debug("AAI Request sent: {}", Serialization.gsonPretty.toJson(aaiNqRequest));
975 AaiNqResponse aaiNqResponse = new AaiManager(new RestManager()).postQuery(getPeManagerEnvProperty(AAI_URL),
976 getPeManagerEnvProperty(AAI_USERNAME_PROPERTY), getPeManagerEnvProperty(AAI_PASS_PROPERTY),
977 aaiNqRequest, onset.getRequestId());
979 // Check AAI response
980 if (aaiNqResponse == null) {
981 logger.warn("No response received from AAI for request {}", aaiNqRequest);
985 // Create AAINQResponseWrapper
986 nqVserverResponse = new AaiNqResponseWrapper(onset.getRequestId(), aaiNqResponse);
988 if (logger.isDebugEnabled()) {
989 logger.debug("AAI Named Query Response: ");
990 logger.debug(Serialization.gsonPretty.toJson(nqVserverResponse.getAaiNqResponse()));
993 return nqVserverResponse;
997 * This method reads and validates environmental properties coming from the policy engine. Null properties cause an
998 * {@link IllegalArgumentException} runtime exception to be thrown
1000 * @param enginePropertyName the name of the parameter to retrieve
1001 * @return the property value
1003 private static String getPeManagerEnvProperty(String enginePropertyName) {
1004 String enginePropertyValue = PolicyEngine.manager.getEnvironmentProperty(enginePropertyName);
1005 if (enginePropertyValue == null) {
1006 throw new IllegalArgumentException("The value of policy engine manager environment property \""
1007 + enginePropertyName + "\" may not be null");
1009 return enginePropertyValue;
1013 public boolean isActive() {
1019 public boolean releaseLock() {
1025 public String toString() {
1026 return "ControlLoopEventManager [closedLoopControlName=" + closedLoopControlName + ", requestId=" + requestId
1027 + ", processor=" + processor + ", onset=" + (onset != null ? onset.getRequestId() : "null")
1028 + ", numOnsets=" + numOnsets + ", numAbatements=" + numAbatements + ", isActivated=" + isActivated
1029 + ", currentOperation=" + currentOperation + ", targetLock=" + targetLock + "]";
1033 * This function calls Aai Custom Query and responds with the AaiCqResponse.
1035 * @param event input event
1036 * @return AaiCqResponse Response from Aai for custom query
1037 * @throws AaiException if error occurs
1039 public AaiCqResponse getCqResponse(VirtualControlLoopEvent event) throws AaiException {
1041 Map<String, String> aai = event.getAai();
1043 if (aai.containsKey(VSERVER_IS_CLOSED_LOOP_DISABLED) || aai.containsKey(GENERIC_VNF_IS_CLOSED_LOOP_DISABLED)) {
1045 if (isClosedLoopDisabled(event)) {
1046 throw new AaiException("is-closed-loop-disabled is set to true on VServer or VNF");
1049 if (isProvStatusInactive(event)) {
1050 throw new AaiException("prov-status is not ACTIVE on VServer or VNF");
1054 if (!aai.containsKey(VSERVER_VSERVER_NAME)) {
1055 throw new AaiException("Vserver name is missing");
1058 UUID reqId = event.getRequestId();
1059 AaiCqResponse response = null;
1060 String vserverId = event.getAai().get(VSERVER_VSERVER_NAME);
1062 String aaiHostUrl = PolicyEngine.manager.getEnvironmentProperty(AAI_URL);
1063 String aaiUser = PolicyEngine.manager.getEnvironmentProperty(AAI_USERNAME_PROPERTY);
1064 String aaiPassword = PolicyEngine.manager.getEnvironmentProperty(AAI_PASS_PROPERTY);
1066 response = new AaiManager(new RestManager()).getCustomQueryResponse(aaiHostUrl, aaiUser, aaiPassword, reqId,