2 * ============LICENSE_START=======================================================
3 * controlloop event manager
4 * ================================================================================
5 * Copyright (C) 2017-2018 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.UUID;
33 import java.util.NoSuchElementException;
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 QUERY_AAI_ERROR_MSG = "Exception from queryAai: ";
81 * Additional time, in seconds, to add to a "lock" request. This ensures that the lock
82 * won't expire right before an operation completes.
84 private static final int ADDITIONAL_LOCK_SEC = 60;
86 private static final Logger logger = LoggerFactory.getLogger(ControlLoopEventManager.class);
88 private static final long serialVersionUID = -1216568161322872641L;
89 public final String closedLoopControlName;
90 public final UUID requestID;
92 private String controlLoopResult;
93 private ControlLoopProcessor processor = null;
94 private VirtualControlLoopEvent onset;
95 private Integer numOnsets = 0;
96 private Integer numAbatements = 0;
97 private VirtualControlLoopEvent abatement;
98 private FinalResult controlLoopTimedOut = null;
100 private boolean isActivated = false;
101 private LinkedList<ControlLoopOperation> controlLoopHistory = new LinkedList<>();
102 private ControlLoopOperationManager currentOperation = null;
103 private ControlLoopOperationManager lastOperationManager = null;
104 private TargetLock targetLock = null;
105 private AaiGetVnfResponse vnfResponse = null;
106 private AaiGetVserverResponse vserverResponse = null;
107 private boolean useTargetLock = true;
110 * Wrapper for AAI vserver named-query response. This is initialized in a lazy
113 private AaiNqResponseWrapper nqVserverResponse = null;
115 private static Collection<String> requiredAAIKeys = new ArrayList<>();
118 requiredAAIKeys.add("AICVServerSelfLink");
119 requiredAAIKeys.add("AICIdentity");
120 requiredAAIKeys.add("is_closed_loop_disabled");
121 requiredAAIKeys.add(VM_NAME);
124 public ControlLoopEventManager(String closedLoopControlName, UUID requestID) {
125 this.closedLoopControlName = closedLoopControlName;
126 this.requestID = requestID;
129 public String getClosedLoopControlName() {
130 return closedLoopControlName;
133 public String getControlLoopResult() {
134 return controlLoopResult;
137 public void setControlLoopResult(String controlLoopResult) {
138 this.controlLoopResult = controlLoopResult;
141 public Integer getNumOnsets() {
145 public void setNumOnsets(Integer numOnsets) {
146 this.numOnsets = numOnsets;
149 public Integer getNumAbatements() {
150 return numAbatements;
153 public void setNumAbatements(Integer numAbatements) {
154 this.numAbatements = numAbatements;
157 public boolean isActivated() {
161 public void setActivated(boolean isActivated) {
162 this.isActivated = isActivated;
165 public boolean useTargetLock() {
166 return useTargetLock();
169 public void setUseTargetLock(boolean useTargetLock) {
170 this.useTargetLock = useTargetLock;
173 public VirtualControlLoopEvent getOnsetEvent() {
177 public VirtualControlLoopEvent getAbatementEvent() {
178 return this.abatement;
181 public ControlLoopProcessor getProcessor() {
182 return this.processor;
185 public UUID getRequestID() {
190 * Activate a control loop event.
192 * @param event the event
193 * @return the VirtualControlLoopNotification
195 public VirtualControlLoopNotification activate(VirtualControlLoopEvent event) {
196 VirtualControlLoopNotification notification = new VirtualControlLoopNotification(event);
199 // This method should ONLY be called ONCE
201 if (this.isActivated) {
202 throw new ControlLoopException("ControlLoopEventManager has already been activated.");
205 // Syntax check the event
207 checkEventSyntax(event);
210 // At this point we are good to go with this event
215 notification.setNotification(ControlLoopNotificationType.ACTIVE);
217 // Set ourselves as active
219 this.isActivated = true;
220 } catch (ControlLoopException e) {
221 logger.error("{}: activate by event threw: ", this, e);
222 notification.setNotification(ControlLoopNotificationType.REJECTED);
223 notification.setMessage(e.getMessage());
229 * Activate a control loop event.
231 * @param yamlSpecification the yaml specification
232 * @param event the event
233 * @return the VirtualControlLoopNotification
235 public VirtualControlLoopNotification activate(String yamlSpecification, VirtualControlLoopEvent event) {
236 VirtualControlLoopNotification notification = new VirtualControlLoopNotification(event);
239 // This method should ONLY be called ONCE
241 if (this.isActivated) {
242 throw new ControlLoopException("ControlLoopEventManager has already been activated.");
245 // Syntax check the event
247 checkEventSyntax(event);
252 if (yamlSpecification == null || yamlSpecification.length() < 1) {
253 throw new ControlLoopException("yaml specification is null or 0 length");
255 } catch (ControlLoopException e) {
256 logger.error("{}: activate by YAML specification and event threw: ", this, e);
257 notification.setNotification(ControlLoopNotificationType.REJECTED);
258 notification.setMessage(e.getMessage());
262 String decodedYaml = null;
264 decodedYaml = URLDecoder.decode(yamlSpecification, "UTF-8");
265 if (decodedYaml != null && decodedYaml.length() > 0) {
266 yamlSpecification = decodedYaml;
268 } catch (UnsupportedEncodingException e) {
269 logger.error("{}: YAML decode in activate by YAML specification and event threw: ", this, e);
270 notification.setNotification(ControlLoopNotificationType.REJECTED);
271 notification.setMessage(e.getMessage());
277 // Parse the YAML specification
279 this.processor = new ControlLoopProcessor(yamlSpecification);
281 // At this point we are good to go with this event
288 notification.setNotification(ControlLoopNotificationType.ACTIVE);
290 // Set ourselves as active
292 this.isActivated = true;
293 } catch (ControlLoopException e) {
294 logger.error("{}: activate by YAML specification and event threw: ", this, e);
295 notification.setNotification(ControlLoopNotificationType.REJECTED);
296 notification.setMessage(e.getMessage());
302 * Check if the control loop is final.
304 * @return a VirtualControlLoopNotification if the control loop is final, otherwise
305 * <code>null</code> is returned
306 * @throws ControlLoopException if an error occurs
308 public VirtualControlLoopNotification isControlLoopFinal() throws ControlLoopException {
310 // Check if they activated us
312 if (!this.isActivated) {
313 throw new ControlLoopException("ControlLoopEventManager MUST be activated first.");
316 // Make sure we are expecting this call.
318 if (this.onset == null) {
319 throw new ControlLoopException("No onset event for ControlLoopEventManager.");
322 // Ok, start creating the notification
324 VirtualControlLoopNotification notification = new VirtualControlLoopNotification(this.onset);
326 // Check if the overall control loop has timed out
328 if (this.isControlLoopTimedOut()) {
330 // Yes we have timed out
332 notification.setNotification(ControlLoopNotificationType.FINAL_FAILURE);
333 notification.setMessage("Control Loop timed out");
334 notification.getHistory().addAll(this.controlLoopHistory);
338 // Check if the current policy is Final
340 FinalResult result = this.processor.checkIsCurrentPolicyFinal();
341 if (result == null) {
343 // we are not at a final result
349 case FINAL_FAILURE_EXCEPTION:
350 notification.setNotification(ControlLoopNotificationType.FINAL_FAILURE);
351 notification.setMessage("Exception in processing closed loop");
354 case FINAL_FAILURE_RETRIES:
355 case FINAL_FAILURE_TIMEOUT:
356 case FINAL_FAILURE_GUARD:
357 notification.setNotification(ControlLoopNotificationType.FINAL_FAILURE);
360 notification.setNotification(ControlLoopNotificationType.FINAL_OPENLOOP);
363 notification.setNotification(ControlLoopNotificationType.FINAL_SUCCESS);
369 // Be sure to add all the history
371 notification.getHistory().addAll(this.controlLoopHistory);
376 * Process the control loop.
378 * @return a ControlLoopOperationManager
379 * @throws ControlLoopException if an error occurs
380 * @throws AaiException if an error occurs retrieving information from A&AI
382 public ControlLoopOperationManager processControlLoop() throws ControlLoopException, AaiException {
384 // Check if they activated us
386 if (!this.isActivated) {
387 throw new ControlLoopException("ControlLoopEventManager MUST be activated first.");
390 // Make sure we are expecting this call.
392 if (this.onset == null) {
393 throw new ControlLoopException("No onset event for ControlLoopEventManager.");
396 // Is there a current operation?
398 if (this.currentOperation != null) {
400 // Throw an exception, or simply return the current operation?
402 throw new ControlLoopException("Already working an Operation, do not call this method.");
405 // Ensure we are not FINAL
407 VirtualControlLoopNotification notification = this.isControlLoopFinal();
408 if (notification != null) {
410 // This is weird, we require them to call the isControlLoopFinal() method first
412 // We should really abstract this and avoid throwing an exception, because it really
413 // isn't an exception.
415 throw new ControlLoopException("Control Loop is in FINAL state, do not call this method.");
418 // Not final so get the policy that needs to be worked on.
420 Policy policy = this.processor.getCurrentPolicy();
421 if (policy == null) {
422 throw new ControlLoopException("ControlLoopEventManager: processor came upon null Policy.");
425 // And setup an operation
427 this.lastOperationManager = this.currentOperation;
428 this.currentOperation = new ControlLoopOperationManager(this.onset, policy, this);
432 return this.currentOperation;
436 * Finish an operation.
438 * @param operation the operation
440 public void finishOperation(ControlLoopOperationManager operation) throws ControlLoopException {
442 // Verify we have a current operation
444 if (this.currentOperation != null) {
446 // Validate they are finishing the current operation
447 // PLD - this is simply comparing the policy. Do we want to equals the whole object?
449 if (this.currentOperation.policy.equals(operation.policy)) {
450 logger.debug("Finishing {} result is {}", this.currentOperation.policy.getRecipe(),
451 this.currentOperation.getOperationResult());
455 this.controlLoopHistory.addAll(this.currentOperation.getHistory());
457 // Move to the next Policy
459 this.processor.nextPolicyForResult(this.currentOperation.getOperationResult());
461 // Just null this out
463 this.lastOperationManager = this.currentOperation;
464 this.currentOperation = null;
466 // TODO: Release our lock
470 logger.debug("Cannot finish current operation {} does not match given operation {}",
471 this.currentOperation.policy, operation.policy);
474 throw new ControlLoopException("No operation to finish.");
478 * Obtain a lock for the current operation.
480 * @return the lock result
481 * @throws ControlLoopException if an error occurs
483 public synchronized LockResult<GuardResult, TargetLock> lockCurrentOperation() throws ControlLoopException {
487 if (this.currentOperation == null) {
488 throw new ControlLoopException("Do not have a current operation.");
491 // Not using target locks? Create and return a lock w/o actually locking.
493 if (!this.useTargetLock) {
494 TargetLock lock = PolicyGuard.createTargetLock(this.currentOperation.policy.getTarget().getType(),
495 this.currentOperation.getTargetEntity(),
496 this.onset.getRequestId(), this);
497 this.targetLock = lock;
498 LockResult<GuardResult, TargetLock> lockResult = 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 =
517 PolicyGuard.lockTarget(this.currentOperation.policy.getTarget().getType(),
518 this.currentOperation.getTargetEntity(), this.onset.getRequestId(), this,
519 this.currentOperation.getOperationTimeout() + ADDITIONAL_LOCK_SEC);
523 if (lockResult.getA().equals(GuardResult.LOCK_ACQUIRED)) {
525 // Yes, let's save it
527 this.targetLock = lockResult.getB();
534 * Release the lock for the current operation.
536 * @return the target lock
538 public synchronized TargetLock unlockCurrentOperation() {
539 if (this.targetLock == null) {
543 TargetLock returnLock = this.targetLock;
544 this.targetLock = null;
546 // if using target locking unlock before returning
548 if (this.useTargetLock) {
549 PolicyGuard.unlockTarget(returnLock);
552 // always return the old target lock so rules can retract it
556 public enum NEW_EVENT_STATUS {
557 FIRST_ONSET, SUBSEQUENT_ONSET, FIRST_ABATEMENT, SUBSEQUENT_ABATEMENT, SYNTAX_ERROR;
561 * An event onset/abatement.
563 * @param event the event
565 * @throws AaiException if an error occurs retrieving information from A&AI
567 public NEW_EVENT_STATUS onNewEvent(VirtualControlLoopEvent event) throws AaiException {
569 this.checkEventSyntax(event);
570 if (event.getClosedLoopEventStatus() == ControlLoopEventStatus.ONSET) {
572 // Check if this is our original ONSET
574 if (event.equals(this.onset)) {
576 // Query A&AI if needed
583 return NEW_EVENT_STATUS.FIRST_ONSET;
586 // Log that we got an onset
589 return NEW_EVENT_STATUS.SUBSEQUENT_ONSET;
590 } else if (event.getClosedLoopEventStatus() == ControlLoopEventStatus.ABATED) {
592 // Have we already got an abatement?
594 if (this.abatement == null) {
598 this.abatement = event;
600 // Keep track that we received another
602 this.numAbatements++;
606 return NEW_EVENT_STATUS.FIRST_ABATEMENT;
609 // Keep track that we received another
611 this.numAbatements++;
615 return NEW_EVENT_STATUS.SUBSEQUENT_ABATEMENT;
618 } catch (ControlLoopException e) {
619 logger.error("{}: onNewEvent threw: ", this, e);
621 return NEW_EVENT_STATUS.SYNTAX_ERROR;
626 * Commit the abatement to the history database.
628 * @param message the abatement message
629 * @param outcome the abatement outcome
631 public void commitAbatement(String message, String outcome) {
632 if (this.lastOperationManager == null) {
633 logger.error("{}: commitAbatement: no operation manager", this);
637 this.lastOperationManager.commitAbatement(message,outcome);
638 } catch (NoSuchElementException e) {
639 logger.error("{}: commitAbatement threw an exception ", this, e);
645 * Set the control loop time out.
647 * @return a VirtualControlLoopNotification
649 public VirtualControlLoopNotification setControlLoopTimedOut() {
650 this.controlLoopTimedOut = FinalResult.FINAL_FAILURE_TIMEOUT;
651 VirtualControlLoopNotification notification = new VirtualControlLoopNotification(this.onset);
652 notification.setNotification(ControlLoopNotificationType.FINAL_FAILURE);
653 notification.setMessage("Control Loop timed out");
654 notification.getHistory().addAll(this.controlLoopHistory);
658 public boolean isControlLoopTimedOut() {
659 return (this.controlLoopTimedOut == FinalResult.FINAL_FAILURE_TIMEOUT);
663 * Get the control loop timeout.
665 * @param defaultTimeout the default timeout
666 * @return the timeout
668 public int getControlLoopTimeout(Integer defaultTimeout) {
669 if (this.processor != null && this.processor.getControlLoop() != null) {
670 return this.processor.getControlLoop().getTimeout();
672 if (defaultTimeout != null) {
673 return defaultTimeout;
678 public AaiGetVnfResponse getVnfResponse() {
682 public AaiGetVserverResponse getVserverResponse() {
683 return vserverResponse;
687 * Check an event syntax.
689 * @param event the event syntax
690 * @throws ControlLoopException if an error occurs
692 public void checkEventSyntax(VirtualControlLoopEvent event) throws ControlLoopException {
693 if (event.getClosedLoopEventStatus() == null
694 || (event.getClosedLoopEventStatus() != ControlLoopEventStatus.ONSET
695 && event.getClosedLoopEventStatus() != ControlLoopEventStatus.ABATED)) {
696 throw new ControlLoopException("Invalid value in closedLoopEventStatus");
698 if (event.getClosedLoopControlName() == null || event.getClosedLoopControlName().length() < 1) {
699 throw new ControlLoopException("No control loop name");
701 if (event.getRequestId() == null) {
702 throw new ControlLoopException("No request ID");
704 if (event.getClosedLoopEventStatus() == ControlLoopEventStatus.ABATED) {
707 if (event.getTarget() == null || event.getTarget().length() < 1) {
708 throw new ControlLoopException("No target field");
709 } else if (!VM_NAME.equalsIgnoreCase(event.getTarget()) && !VNF_NAME.equalsIgnoreCase(event.getTarget())
710 && !VSERVER_VSERVER_NAME.equalsIgnoreCase(event.getTarget())
711 && !GENERIC_VNF_VNF_ID.equalsIgnoreCase(event.getTarget())
712 && !GENERIC_VNF_VNF_NAME.equalsIgnoreCase(event.getTarget())) {
713 throw new ControlLoopException("target field invalid - expecting VM_NAME or VNF_NAME");
715 if (event.getAai() == null) {
716 throw new ControlLoopException("AAI is null");
718 if (event.getAai().get(GENERIC_VNF_VNF_ID) == null && event.getAai().get(VSERVER_VSERVER_NAME) == null
719 && event.getAai().get(GENERIC_VNF_VNF_NAME) == null) {
720 throw new ControlLoopException(
721 "generic-vnf.vnf-id or generic-vnf.vnf-name or vserver.vserver-name information missing");
726 * Query A&AI for an event.
728 * @param event the event
729 * @throws AaiException if an error occurs retrieving information from A&AI
731 public void queryAai(VirtualControlLoopEvent event) throws AaiException {
733 Map<String, String> aai = event.getAai();
735 if (aai.containsKey(VSERVER_IS_CLOSED_LOOP_DISABLED) || aai.containsKey(GENERIC_VNF_IS_CLOSED_LOOP_DISABLED)) {
737 if (isClosedLoopDisabled(event)) {
738 throw new AaiException("is-closed-loop-disabled is set to true on VServer or VNF");
741 if (isProvStatusInactive(event)) {
742 throw new AaiException("prov-status is not ACTIVE on VServer or VNF");
745 // no need to query, as we already have the data
749 if (vnfResponse != null || vserverResponse != null) {
750 // query has already been performed
755 if (aai.containsKey(GENERIC_VNF_VNF_ID) || aai.containsKey(GENERIC_VNF_VNF_NAME)) {
756 vnfResponse = getAAIVnfInfo(event);
757 processVNFResponse(vnfResponse, aai.containsKey(GENERIC_VNF_VNF_ID));
758 } else if (aai.containsKey(VSERVER_VSERVER_NAME)) {
759 vserverResponse = getAAIVserverInfo(event);
760 processVServerResponse(vserverResponse);
762 } catch (AaiException e) {
763 logger.error(QUERY_AAI_ERROR_MSG, e);
765 } catch (Exception e) {
766 logger.error(QUERY_AAI_ERROR_MSG, e);
767 throw new AaiException(QUERY_AAI_ERROR_MSG + e.toString());
772 * Process a response from A&AI for a VNF.
774 * @param aaiResponse the response from A&AI
775 * @param queryByVnfId <code>true</code> if the query was based on vnf-id,
776 * <code>false</code> if the query was based on vnf-name
777 * @throws AaiException if an error occurs processing the response
779 private static void processVNFResponse(AaiGetVnfResponse aaiResponse, boolean queryByVNFID) throws AaiException {
780 String queryTypeString = (queryByVNFID ? "vnf-id" : "vnf-name");
782 if (aaiResponse == null) {
783 throw new AaiException("AAI Response is null (query by " + queryTypeString + ")");
785 if (aaiResponse.getRequestError() != null) {
786 throw new AaiException("AAI Responded with a request error (query by " + queryTypeString + ")");
789 if (aaiResponse.getIsClosedLoopDisabled()) {
790 throw new AaiException("is-closed-loop-disabled is set to true (query by " + queryTypeString + ")");
793 if (!PROV_STATUS_ACTIVE.equals(aaiResponse.getProvStatus())) {
794 throw new AaiException("prov-status is not ACTIVE (query by " + queryTypeString + ")");
799 * Process a response from A&AI for a VServer.
801 * @param aaiResponse the response from A&AI
802 * @throws AaiException if an error occurs processing the response
804 private static void processVServerResponse(AaiGetVserverResponse aaiResponse) throws AaiException {
805 if (aaiResponse == null) {
806 throw new AaiException("AAI Response is null (query by vserver-name)");
808 if (aaiResponse.getRequestError() != null) {
809 throw new AaiException("AAI Responded with a request error (query by vserver-name)");
812 List<AaiNqVServer> lst = aaiResponse.getVserver();
817 AaiNqVServer svr = lst.get(0);
818 if (svr.getIsClosedLoopDisabled()) {
819 throw new AaiException("is-closed-loop-disabled is set to true (query by vserver-name)");
822 if (!PROV_STATUS_ACTIVE.equals(svr.getProvStatus())) {
823 throw new AaiException("prov-status is not ACTIVE (query by vserver-name)");
828 * Is closed loop disabled for an event.
830 * @param event the event
831 * @return <code>true</code> if the control loop is disabled, <code>false</code>
834 public static boolean isClosedLoopDisabled(VirtualControlLoopEvent event) {
835 Map<String, String> aai = event.getAai();
836 return (isAaiTrue(aai.get(VSERVER_IS_CLOSED_LOOP_DISABLED))
837 || isAaiTrue(aai.get(GENERIC_VNF_IS_CLOSED_LOOP_DISABLED)));
841 * Does provisioning status, for an event, have a value other than ACTIVE.
843 * @param event the event
844 * @return {@code true} if the provisioning status is neither ACTIVE nor {@code null},
845 * {@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
858 * value is {@code null}
860 protected static boolean isAaiTrue(String aaiValue) {
861 return ("true".equalsIgnoreCase(aaiValue) || "T".equalsIgnoreCase(aaiValue) || "yes".equalsIgnoreCase(aaiValue)
862 || "Y".equalsIgnoreCase(aaiValue));
866 * Get the A&AI VService information for an event.
868 * @param event the event
869 * @return a AaiGetVserverResponse
870 * @throws ControlLoopException if an error occurs
872 public static AaiGetVserverResponse getAAIVserverInfo(VirtualControlLoopEvent event) throws ControlLoopException {
873 UUID requestId = event.getRequestId();
874 AaiGetVserverResponse response = null;
875 String vserverName = event.getAai().get(VSERVER_VSERVER_NAME);
878 if (vserverName != null) {
879 String aaiHostUrl = PolicyEngine.manager.getEnvironmentProperty("aai.url");
880 String aaiUser = PolicyEngine.manager.getEnvironmentProperty("aai.username");
881 String aaiPassword = PolicyEngine.manager.getEnvironmentProperty("aai.password");
882 String aaiGetQueryByVserver = "/aai/v11/nodes/vservers?vserver-name=";
883 String url = aaiHostUrl + aaiGetQueryByVserver;
884 logger.info("AAI Host URL by VServer: {}", url);
885 response = new AaiManager(new RESTManager()).getQueryByVserverName(url, aaiUser, aaiPassword, requestId,
888 } catch (Exception e) {
889 logger.error("getAAIVserverInfo exception: ", e);
890 throw new ControlLoopException("Exception in getAAIVserverInfo: ", e);
897 * Get A&AI VNF information for an event.
899 * @param event the event
900 * @return a AaiGetVnfResponse
901 * @throws ControlLoopException if an error occurs
903 public static AaiGetVnfResponse getAAIVnfInfo(VirtualControlLoopEvent event) throws ControlLoopException {
904 UUID requestId = event.getRequestId();
905 AaiGetVnfResponse response = null;
906 String vnfName = event.getAai().get(GENERIC_VNF_VNF_NAME);
907 String vnfId = event.getAai().get(GENERIC_VNF_VNF_ID);
909 String aaiHostUrl = PolicyEngine.manager.getEnvironmentProperty("aai.url");
910 String aaiUser = PolicyEngine.manager.getEnvironmentProperty("aai.username");
911 String aaiPassword = PolicyEngine.manager.getEnvironmentProperty("aai.password");
914 if (vnfName != null) {
915 String aaiGetQueryByVnfName = "/aai/v11/network/generic-vnfs/generic-vnf?vnf-name=";
916 String url = aaiHostUrl + aaiGetQueryByVnfName;
917 logger.info("AAI Host URL by VNF name: {}", url);
918 response = new AaiManager(new RESTManager()).getQueryByVnfName(url, aaiUser, aaiPassword, requestId,
920 } else if (vnfId != null) {
921 String aaiGetQueryByVnfId = "/aai/v11/network/generic-vnfs/generic-vnf/";
922 String url = aaiHostUrl + aaiGetQueryByVnfId;
923 logger.info("AAI Host URL by VNF ID: {}", url);
925 new AaiManager(new RESTManager()).getQueryByVnfId(url, aaiUser, aaiPassword, requestId, vnfId);
927 } catch (Exception e) {
928 logger.error("getAAIVnfInfo exception: ", e);
929 throw new ControlLoopException("Exception in getAAIVnfInfo: ", e);
936 * 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 // TODO: UUID.fromString($params.getAaiNamedQueryUUID()) AaiNamedQueryUUID
959 aaiNqNamedQuery.setNamedQueryUuid(UUID.fromString("4ff56a54-9e3f-46b7-a337-07a1d3c6b469"));
960 aaiNqQueryParam.setNamedQuery(aaiNqNamedQuery);
961 aaiNqRequest.setQueryParameters(aaiNqQueryParam);
965 Map<String, Map<String, String>> aaiNqInstanceFilterMap = new HashMap<>();
966 Map<String, String> aaiNqInstanceFilterMapItem = new HashMap<>();
967 aaiNqInstanceFilterMapItem.put("vserver-name", vserverName);
968 aaiNqInstanceFilterMap.put("vserver", aaiNqInstanceFilterMapItem);
969 aaiNqInstanceFilter.getInstanceFilter().add(aaiNqInstanceFilterMap);
970 aaiNqRequest.setInstanceFilters(aaiNqInstanceFilter);
972 if (logger.isDebugEnabled()) {
973 logger.debug("AAI Request sent: {}", Serialization.gsonPretty.toJson(aaiNqRequest));
976 AaiNqResponse aaiNqResponse = new AaiManager(new RESTManager()).postQuery(getPeManagerEnvProperty("aai.url"),
977 getPeManagerEnvProperty("aai.username"), getPeManagerEnvProperty("aai.password"), aaiNqRequest,
978 onset.getRequestId());
980 // Check AAI response
981 if (aaiNqResponse == null) {
982 logger.warn("No response received from AAI for request {}", aaiNqRequest);
986 // Create AAINQResponseWrapper
987 nqVserverResponse = new AaiNqResponseWrapper(onset.getRequestId(), aaiNqResponse);
989 if (logger.isDebugEnabled()) {
990 logger.debug("AAI Named Query Response: ");
991 logger.debug(Serialization.gsonPretty.toJson(nqVserverResponse.getAaiNqResponse()));
994 return nqVserverResponse;
998 * This method reads and validates environmental properties coming from the policy engine. Null
999 * properties cause an {@link IllegalArgumentException} runtime exception to be thrown
1001 * @param enginePropertyName the name of the parameter to retrieve
1002 * @return the property value
1004 private static String getPeManagerEnvProperty(String enginePropertyName) {
1005 String enginePropertyValue = PolicyEngine.manager.getEnvironmentProperty(enginePropertyName);
1006 if (enginePropertyValue == null) {
1007 throw new IllegalArgumentException("The value of policy engine manager environment property \""
1008 + enginePropertyName + "\" may not be null");
1010 return enginePropertyValue;
1014 public boolean isActive() {
1020 public boolean releaseLock() {
1026 public String toString() {
1027 return "ControlLoopEventManager [closedLoopControlName=" + closedLoopControlName + ", requestID=" + requestID
1028 + ", processor=" + processor + ", onset=" + (onset != null ? onset.getRequestId() : "null")
1029 + ", numOnsets=" + numOnsets + ", numAbatements=" + numAbatements + ", isActivated=" + isActivated
1030 + ", currentOperation=" + currentOperation + ", targetLock=" + targetLock + "]";