fa608ca082777084ebd67d627fe324d7d93aaba8
[policy/drools-applications.git] /
1 /*-
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
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
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=========================================================
19  */
20
21 package org.onap.policy.controlloop.eventmanager;
22
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.LinkedList;
29 import java.util.UUID;
30
31 import org.onap.policy.aai.AaiGetVnfResponse;
32 import org.onap.policy.aai.AaiGetVserverResponse;
33 import org.onap.policy.aai.AaiManager;
34 import org.onap.policy.aai.util.AaiException;
35 import org.onap.policy.controlloop.ControlLoopEventStatus;
36 import org.onap.policy.controlloop.ControlLoopException;
37 import org.onap.policy.controlloop.ControlLoopNotificationType;
38 import org.onap.policy.controlloop.ControlLoopOperation;
39 import org.onap.policy.controlloop.VirtualControlLoopEvent;
40 import org.onap.policy.controlloop.VirtualControlLoopNotification;
41 import org.onap.policy.controlloop.policy.FinalResult;
42 import org.onap.policy.controlloop.policy.Policy;
43 import org.onap.policy.controlloop.processor.ControlLoopProcessor;
44 import org.onap.policy.drools.system.PolicyEngine;
45 import org.onap.policy.guard.GuardResult;
46 import org.onap.policy.guard.LockCallback;
47 import org.onap.policy.guard.PolicyGuard;
48 import org.onap.policy.guard.PolicyGuard.LockResult;
49 import org.onap.policy.guard.TargetLock;
50 import org.onap.policy.rest.RESTManager;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54 public class ControlLoopEventManager implements LockCallback, Serializable {
55     private static final String VM_NAME = "VM_NAME";
56     private static final String VNF_NAME = "VNF_NAME";
57     private static final String GENERIC_VNF_VNF_ID = "generic-vnf.vnf-id";
58     private static final String GENERIC_VNF_VNF_NAME = "generic-vnf.vnf-name";
59     private static final String VSERVER_VSERVER_NAME = "vserver.vserver-name";
60     private static final String GENERIC_VNF_IS_CLOSED_LOOP_DISABLED = "generic-vnf.is-closed-loop-disabled";
61     private static final String VSERVER_IS_CLOSED_LOOP_DISABLED = "vserver.is-closed-loop-disabled";
62
63     /**
64      * Additional time, in seconds, to add to a "lock" request. This ensures that the lock
65      * won't expire right before an operation completes.
66      */
67     private static final int ADDITIONAL_LOCK_SEC = 60;
68
69     private static final Logger logger = LoggerFactory.getLogger(ControlLoopEventManager.class);
70
71     private static final long serialVersionUID = -1216568161322872641L;
72     public final String closedLoopControlName;
73     public final UUID requestID;
74
75     private String controlLoopResult;
76     private transient ControlLoopProcessor processor = null;
77     private VirtualControlLoopEvent onset;
78     private Integer numOnsets = 0;
79     private Integer numAbatements = 0;
80     private VirtualControlLoopEvent abatement;
81     private FinalResult controlLoopTimedOut = null;
82
83     private boolean isActivated = false;
84     private LinkedList<ControlLoopOperation> controlLoopHistory = new LinkedList<>();
85     private ControlLoopOperationManager currentOperation = null;
86     private transient TargetLock targetLock = null;
87     private AaiGetVnfResponse vnfResponse = null;
88     private AaiGetVserverResponse vserverResponse = null;
89
90     private static Collection<String> requiredAAIKeys = new ArrayList<>();
91
92     static {
93         requiredAAIKeys.add("AICVServerSelfLink");
94         requiredAAIKeys.add("AICIdentity");
95         requiredAAIKeys.add("is_closed_loop_disabled");
96         requiredAAIKeys.add(VM_NAME);
97     }
98
99     public ControlLoopEventManager(String closedLoopControlName, UUID requestID) {
100         this.closedLoopControlName = closedLoopControlName;
101         this.requestID = requestID;
102     }
103
104     public String getClosedLoopControlName() {
105         return closedLoopControlName;
106     }
107
108     public String getControlLoopResult() {
109         return controlLoopResult;
110     }
111
112     public void setControlLoopResult(String controlLoopResult) {
113         this.controlLoopResult = controlLoopResult;
114     }
115
116     public Integer getNumOnsets() {
117         return numOnsets;
118     }
119
120     public void setNumOnsets(Integer numOnsets) {
121         this.numOnsets = numOnsets;
122     }
123
124     public Integer getNumAbatements() {
125         return numAbatements;
126     }
127
128     public void setNumAbatements(Integer numAbatements) {
129         this.numAbatements = numAbatements;
130     }
131
132     public boolean isActivated() {
133         return isActivated;
134     }
135
136     public void setActivated(boolean isActivated) {
137         this.isActivated = isActivated;
138     }
139
140     public VirtualControlLoopEvent getOnsetEvent() {
141         return this.onset;
142     }
143
144     public VirtualControlLoopEvent getAbatementEvent() {
145         return this.abatement;
146     }
147
148     public ControlLoopProcessor getProcessor() {
149         return this.processor;
150     }
151
152     public UUID getRequestID() {
153         return requestID;
154     }
155
156     /**
157      * Activate a control loop event.
158      * 
159      * @param event the event
160      * @return the VirtualControlLoopNotification
161      */
162     public VirtualControlLoopNotification activate(VirtualControlLoopEvent event) {
163         VirtualControlLoopNotification notification = new VirtualControlLoopNotification(event);
164         try {
165             //
166             // This method should ONLY be called ONCE
167             //
168             if (this.isActivated) {
169                 throw new ControlLoopException("ControlLoopEventManager has already been activated.");
170             }
171             //
172             // Syntax check the event
173             //
174             checkEventSyntax(event);
175
176             //
177             // At this point we are good to go with this event
178             //
179             this.onset = event;
180             this.numOnsets = 1;
181             //
182             notification.setNotification(ControlLoopNotificationType.ACTIVE);
183             //
184             // Set ourselves as active
185             //
186             this.isActivated = true;
187         } catch (ControlLoopException e) {
188             logger.error("{}: activate by event threw: ", this, e);
189             notification.setNotification(ControlLoopNotificationType.REJECTED);
190             notification.setMessage(e.getMessage());
191         }
192         return notification;
193     }
194
195     /**
196      * Activate a control loop event.
197      * 
198      * @param yamlSpecification the yaml specification
199      * @param event the event
200      * @return the VirtualControlLoopNotification
201      */
202     public VirtualControlLoopNotification activate(String yamlSpecification, VirtualControlLoopEvent event) {
203         VirtualControlLoopNotification notification = new VirtualControlLoopNotification(event);
204         try {
205             //
206             // This method should ONLY be called ONCE
207             //
208             if (this.isActivated) {
209                 throw new ControlLoopException("ControlLoopEventManager has already been activated.");
210             }
211             //
212             // Syntax check the event
213             //
214             checkEventSyntax(event);
215
216             //
217             // Check the YAML
218             //
219             if (yamlSpecification == null || yamlSpecification.length() < 1) {
220                 throw new ControlLoopException("yaml specification is null or 0 length");
221             }
222         } catch (ControlLoopException e) {
223             logger.error("{}: activate by YAML specification and event threw: ", this, e);
224             notification.setNotification(ControlLoopNotificationType.REJECTED);
225             notification.setMessage(e.getMessage());
226             return notification;
227         }
228
229         String decodedYaml = null;
230         try {
231             decodedYaml = URLDecoder.decode(yamlSpecification, "UTF-8");
232             if (decodedYaml != null && decodedYaml.length() > 0) {
233                 yamlSpecification = decodedYaml;
234             }
235         } catch (UnsupportedEncodingException e) {
236             logger.error("{}: YAML decode in activate by YAML specification and event threw: ", this, e);
237             notification.setNotification(ControlLoopNotificationType.REJECTED);
238             notification.setMessage(e.getMessage());
239             return notification;
240         }
241
242         try {
243             //
244             // Parse the YAML specification
245             //
246             this.processor = new ControlLoopProcessor(yamlSpecification);
247
248             //
249             // At this point we are good to go with this event
250             //
251             this.onset = event;
252             this.numOnsets = 1;
253             //
254             //
255             //
256             notification.setNotification(ControlLoopNotificationType.ACTIVE);
257             //
258             // Set ourselves as active
259             //
260             this.isActivated = true;
261         } catch (ControlLoopException e) {
262             logger.error("{}: activate by YAML specification and event threw: ", this, e);
263             notification.setNotification(ControlLoopNotificationType.REJECTED);
264             notification.setMessage(e.getMessage());
265         }
266         return notification;
267     }
268
269     /**
270      * Check if the control loop is final.
271      * 
272      * @return a VirtualControlLoopNotification if the control loop is final, otherwise
273      *         <code>null</code> is returned
274      * @throws ControlLoopException if an error occurs
275      */
276     public VirtualControlLoopNotification isControlLoopFinal() throws ControlLoopException {
277         //
278         // Check if they activated us
279         //
280         if (!this.isActivated) {
281             throw new ControlLoopException("ControlLoopEventManager MUST be activated first.");
282         }
283         //
284         // Make sure we are expecting this call.
285         //
286         if (this.onset == null) {
287             throw new ControlLoopException("No onset event for ControlLoopEventManager.");
288         }
289         //
290         // Ok, start creating the notification
291         //
292         VirtualControlLoopNotification notification = new VirtualControlLoopNotification(this.onset);
293         //
294         // Check if the overall control loop has timed out
295         //
296         if (this.isControlLoopTimedOut()) {
297             //
298             // Yes we have timed out
299             //
300             notification.setNotification(ControlLoopNotificationType.FINAL_FAILURE);
301             notification.setMessage("Control Loop timed out");
302             notification.getHistory().addAll(this.controlLoopHistory);
303             return notification;
304         }
305         //
306         // Check if the current policy is Final
307         //
308         FinalResult result = this.processor.checkIsCurrentPolicyFinal();
309         if (result == null) {
310             //
311             // we are not at a final result
312             //
313             return null;
314         }
315
316         switch (result) {
317             case FINAL_FAILURE_EXCEPTION:
318                 notification.setNotification(ControlLoopNotificationType.FINAL_FAILURE);
319                 notification.setMessage("Exception in processing closed loop");
320                 break;
321             case FINAL_FAILURE:
322             case FINAL_FAILURE_RETRIES:
323             case FINAL_FAILURE_TIMEOUT:
324             case FINAL_FAILURE_GUARD:
325                 notification.setNotification(ControlLoopNotificationType.FINAL_FAILURE);
326                 break;
327             case FINAL_OPENLOOP:
328                 notification.setNotification(ControlLoopNotificationType.FINAL_OPENLOOP);
329                 break;
330             case FINAL_SUCCESS:
331                 notification.setNotification(ControlLoopNotificationType.FINAL_SUCCESS);
332                 break;
333             default:
334                 return null;
335         }
336         //
337         // Be sure to add all the history
338         //
339         notification.getHistory().addAll(this.controlLoopHistory);
340         return notification;
341     }
342
343     /**
344      * Process the control loop.
345      * 
346      * @return a ControlLoopOperationManager
347      * @throws ControlLoopException if an error occurs
348      * @throws AaiException if an error occurs retrieving information from A&AI
349      */
350     public ControlLoopOperationManager processControlLoop() throws ControlLoopException, AaiException {
351         //
352         // Check if they activated us
353         //
354         if (!this.isActivated) {
355             throw new ControlLoopException("ControlLoopEventManager MUST be activated first.");
356         }
357         //
358         // Make sure we are expecting this call.
359         //
360         if (this.onset == null) {
361             throw new ControlLoopException("No onset event for ControlLoopEventManager.");
362         }
363         //
364         // Is there a current operation?
365         //
366         if (this.currentOperation != null) {
367             //
368             // Throw an exception, or simply return the current operation?
369             //
370             throw new ControlLoopException("Already working an Operation, do not call this method.");
371         }
372         //
373         // Ensure we are not FINAL
374         //
375         VirtualControlLoopNotification notification = this.isControlLoopFinal();
376         if (notification != null) {
377             //
378             // This is weird, we require them to call the isControlLoopFinal() method first
379             //
380             // We should really abstract this and avoid throwing an exception, because it really
381             // isn't an exception.
382             //
383             throw new ControlLoopException("Control Loop is in FINAL state, do not call this method.");
384         }
385         //
386         // Not final so get the policy that needs to be worked on.
387         //
388         Policy policy = this.processor.getCurrentPolicy();
389         if (policy == null) {
390             throw new ControlLoopException("ControlLoopEventManager: processor came upon null Policy.");
391         }
392         //
393         // And setup an operation
394         //
395         this.currentOperation = new ControlLoopOperationManager(this.onset, policy, this);
396         //
397         // Return it
398         //
399         return this.currentOperation;
400     }
401
402     /**
403      * Finish an operation.
404      * 
405      * @param operation the operation
406      */
407     public void finishOperation(ControlLoopOperationManager operation) throws ControlLoopException {
408         //
409         // Verify we have a current operation
410         //
411         if (this.currentOperation != null) {
412             //
413             // Validate they are finishing the current operation
414             // PLD - this is simply comparing the policy. Do we want to equals the whole object?
415             //
416             if (this.currentOperation.policy.equals(operation.policy)) {
417                 logger.debug("Finishing {} result is {}", this.currentOperation.policy.getRecipe(),
418                         this.currentOperation.getOperationResult());
419                 //
420                 // Save history
421                 //
422                 this.controlLoopHistory.addAll(this.currentOperation.getHistory());
423                 //
424                 // Move to the next Policy
425                 //
426                 this.processor.nextPolicyForResult(this.currentOperation.getOperationResult());
427                 //
428                 // Just null this out
429                 //
430                 this.currentOperation = null;
431                 //
432                 // TODO: Release our lock
433                 //
434                 return;
435             }
436             logger.debug("Cannot finish current operation {} does not match given operation {}",
437                     this.currentOperation.policy, operation.policy);
438             return;
439         }
440         throw new ControlLoopException("No operation to finish.");
441     }
442
443     /**
444      * Obtain a lock for the current operation.
445      * 
446      * @return the lock result
447      * @throws ControlLoopException if an error occurs
448      */
449     public synchronized LockResult<GuardResult, TargetLock> lockCurrentOperation() throws ControlLoopException {
450         //
451         // Sanity check
452         //
453         if (this.currentOperation == null) {
454             throw new ControlLoopException("Do not have a current operation.");
455         }
456         //
457         // Have we acquired it already?
458         //
459         if (this.targetLock != null) {
460             //
461             // TODO: Make sure the current lock is for the same target.
462             // Currently, it should be. But in the future it may not.
463             //
464             GuardResult result = PolicyGuard.lockTarget(targetLock,
465                             this.currentOperation.getOperationTimeout() + ADDITIONAL_LOCK_SEC);
466             return new LockResult<>(result, this.targetLock);
467         } else {
468             //
469             // Ask the Guard
470             //
471             LockResult<GuardResult, TargetLock> lockResult =
472                     PolicyGuard.lockTarget(this.currentOperation.policy.getTarget().getType(),
473                             this.currentOperation.getTargetEntity(), this.onset.getRequestId(), this,
474                             this.currentOperation.getOperationTimeout() + ADDITIONAL_LOCK_SEC);
475             //
476             // Was it acquired?
477             //
478             if (lockResult.getA().equals(GuardResult.LOCK_ACQUIRED)) {
479                 //
480                 // Yes, let's save it
481                 //
482                 this.targetLock = lockResult.getB();
483             }
484             return lockResult;
485         }
486     }
487
488     /**
489      * Release the lock for the current operation.
490      * 
491      * @return the target lock
492      */
493     public synchronized TargetLock unlockCurrentOperation() {
494         if (this.targetLock == null) {
495             return null;
496         }
497         
498         TargetLock returnLock = this.targetLock;
499         this.targetLock = null;
500         
501         PolicyGuard.unlockTarget(returnLock);
502         
503         // always return the old target lock so rules can retract it
504         return returnLock;
505     }
506
507     public enum NEW_EVENT_STATUS {
508         FIRST_ONSET, SUBSEQUENT_ONSET, FIRST_ABATEMENT, SUBSEQUENT_ABATEMENT, SYNTAX_ERROR;
509     }
510
511     /**
512      * An event onset/abatement.
513      * 
514      * @param event the event
515      * @return the status
516      * @throws AaiException if an error occurs retrieving information from A&AI
517      */
518     public NEW_EVENT_STATUS onNewEvent(VirtualControlLoopEvent event) throws AaiException {
519         try {
520             this.checkEventSyntax(event);
521             if (event.getClosedLoopEventStatus() == ControlLoopEventStatus.ONSET) {
522                 //
523                 // Check if this is our original ONSET
524                 //
525                 if (event.equals(this.onset)) {
526                     //
527                     // Query A&AI if needed
528                     //
529                     queryAai(event);
530
531                     //
532                     // DO NOT retract it
533                     //
534                     return NEW_EVENT_STATUS.FIRST_ONSET;
535                 }
536                 //
537                 // Log that we got an onset
538                 //
539                 this.numOnsets++;
540                 return NEW_EVENT_STATUS.SUBSEQUENT_ONSET;
541             } else if (event.getClosedLoopEventStatus() == ControlLoopEventStatus.ABATED) {
542                 //
543                 // Have we already got an abatement?
544                 //
545                 if (this.abatement == null) {
546                     //
547                     // Save this
548                     //
549                     this.abatement = event;
550                     //
551                     // Keep track that we received another
552                     //
553                     this.numAbatements++;
554                     //
555                     //
556                     //
557                     return NEW_EVENT_STATUS.FIRST_ABATEMENT;
558                 } else {
559                     //
560                     // Keep track that we received another
561                     //
562                     this.numAbatements++;
563                     //
564                     //
565                     //
566                     return NEW_EVENT_STATUS.SUBSEQUENT_ABATEMENT;
567                 }
568             }
569         } catch (ControlLoopException e) {
570             logger.error("{}: onNewEvent threw: ", this, e);
571         }
572         return NEW_EVENT_STATUS.SYNTAX_ERROR;
573     }
574
575     /**
576      * Set the control loop time out.
577      * 
578      * @return a VirtualControlLoopNotification
579      */
580     public VirtualControlLoopNotification setControlLoopTimedOut() {
581         this.controlLoopTimedOut = FinalResult.FINAL_FAILURE_TIMEOUT;
582         VirtualControlLoopNotification notification = new VirtualControlLoopNotification(this.onset);
583         notification.setNotification(ControlLoopNotificationType.FINAL_FAILURE);
584         notification.setMessage("Control Loop timed out");
585         notification.getHistory().addAll(this.controlLoopHistory);
586         return notification;
587     }
588
589     public boolean isControlLoopTimedOut() {
590         return (this.controlLoopTimedOut == FinalResult.FINAL_FAILURE_TIMEOUT);
591     }
592
593     /**
594      * Get the control loop timeout.
595      * 
596      * @param defaultTimeout the default timeout
597      * @return the timeout
598      */
599     public int getControlLoopTimeout(Integer defaultTimeout) {
600         if (this.processor != null && this.processor.getControlLoop() != null) {
601             return this.processor.getControlLoop().getTimeout();
602         }
603         if (defaultTimeout != null) {
604             return defaultTimeout;
605         }
606         return 0;
607     }
608
609     public AaiGetVnfResponse getVnfResponse() {
610         return vnfResponse;
611     }
612
613     public AaiGetVserverResponse getVserverResponse() {
614         return vserverResponse;
615     }
616
617     /**
618      * Check an event syntax.
619      * 
620      * @param event the event syntax
621      * @throws ControlLoopException if an error occurs
622      */
623     public void checkEventSyntax(VirtualControlLoopEvent event) throws ControlLoopException {
624         if (event.getClosedLoopEventStatus() == null
625                 || (event.getClosedLoopEventStatus() != ControlLoopEventStatus.ONSET
626                         && event.getClosedLoopEventStatus() != ControlLoopEventStatus.ABATED)) {
627             throw new ControlLoopException("Invalid value in closedLoopEventStatus");
628         }
629         if (event.getClosedLoopControlName() == null || event.getClosedLoopControlName().length() < 1) {
630             throw new ControlLoopException("No control loop name");
631         }
632         if (event.getRequestId() == null) {
633             throw new ControlLoopException("No request ID");
634         }
635         if (event.getClosedLoopEventStatus() == ControlLoopEventStatus.ABATED) {
636             return;
637         }
638         if (event.getTarget() == null || event.getTarget().length() < 1) {
639             throw new ControlLoopException("No target field");
640         } else if (!VM_NAME.equalsIgnoreCase(event.getTarget()) && !VNF_NAME.equalsIgnoreCase(event.getTarget())
641                 && !VSERVER_VSERVER_NAME.equalsIgnoreCase(event.getTarget())
642                 && !GENERIC_VNF_VNF_ID.equalsIgnoreCase(event.getTarget())
643                 && !GENERIC_VNF_VNF_NAME.equalsIgnoreCase(event.getTarget())) {
644             throw new ControlLoopException("target field invalid - expecting VM_NAME or VNF_NAME");
645         }
646         if (event.getAai() == null) {
647             throw new ControlLoopException("AAI is null");
648         }
649         if (event.getAai().get(GENERIC_VNF_VNF_ID) == null && event.getAai().get(VSERVER_VSERVER_NAME) == null
650                 && event.getAai().get(GENERIC_VNF_VNF_NAME) == null) {
651             throw new ControlLoopException(
652                     "generic-vnf.vnf-id or generic-vnf.vnf-name or vserver.vserver-name information missing");
653         }
654     }
655
656     /**
657      * Query A&AI for an event.
658      * 
659      * @param event the event
660      * @throws AaiException if an error occurs retrieving information from A&AI
661      */
662     public void queryAai(VirtualControlLoopEvent event) throws AaiException {        
663         if (event.getAai().get(VSERVER_IS_CLOSED_LOOP_DISABLED) != null
664                 || event.getAai().get(GENERIC_VNF_IS_CLOSED_LOOP_DISABLED) != null) {
665             
666             if(isClosedLoopDisabled(event)) {
667                 throw new AaiException("is-closed-loop-disabled is set to true on VServer or VNF");
668             }
669             
670             // no need to query, as we already have the data
671             return;
672         }
673         
674         if(vnfResponse != null || vserverResponse != null) {
675             // query has already been performed
676             return;
677         }
678
679         try {
680             if (event.getAai().get(GENERIC_VNF_VNF_ID) != null || event.getAai().get(GENERIC_VNF_VNF_NAME) != null) {
681                 vnfResponse = getAAIVnfInfo(event);
682                 processVNFResponse(vnfResponse, event.getAai().get(GENERIC_VNF_VNF_ID) != null);
683             } else if (event.getAai().get(VSERVER_VSERVER_NAME) != null) {
684                 vserverResponse = getAAIVserverInfo(event);
685                 processVServerResponse(vserverResponse);
686             }
687         } catch (Exception e) {
688             logger.error("Exception from queryAai: ", e);
689             throw new AaiException("Exception from queryAai: " + e.toString());
690         }
691     }
692
693     /**
694      * Process a response from A&AI for a VNF.
695      * 
696      * @param aaiResponse the response from A&AI
697      * @param queryByVnfId <code>true</code> if the query was based on vnf-id, <code>false</code> if
698      *        the query was based on vnf-name
699      * @throws AaiException if an error occurs processing the response
700      */
701     private static void processVNFResponse(AaiGetVnfResponse aaiResponse, boolean queryByVNFID) throws AaiException {
702         String queryTypeString = (queryByVNFID ? "vnf-id" : "vnf-name");
703
704         if (aaiResponse == null) {
705             throw new AaiException("AAI Response is null (query by " + queryTypeString + ")");
706         }
707         if (aaiResponse.getRequestError() != null) {
708             throw new AaiException("AAI Responded with a request error (query by " + queryTypeString + ")");
709         }
710
711         if (aaiResponse.getIsClosedLoopDisabled() != null) {
712             String value = aaiResponse.getIsClosedLoopDisabled();
713             if ("true".equalsIgnoreCase(value) || "T".equalsIgnoreCase(value) || "yes".equalsIgnoreCase(value)
714                     || "Y".equalsIgnoreCase(value)) {
715                 throw new AaiException("is-closed-loop-disabled is set to true (query by " + queryTypeString + ")");
716             }
717         }
718     }
719
720     private static void processVServerResponse(AaiGetVserverResponse aaiResponse) throws AaiException {
721         if (aaiResponse == null) {
722             throw new AaiException("AAI Response is null (query by vserver-name)");
723         }
724         if (aaiResponse.getRequestError() != null) {
725             throw new AaiException("AAI responded with a request error (query by vserver-name)");
726         }
727
728         if (aaiResponse.getIsClosedLoopDisabled() != null) {
729             String value = aaiResponse.getIsClosedLoopDisabled();
730             if ("true".equalsIgnoreCase(value) || "T".equalsIgnoreCase(value) || "yes".equalsIgnoreCase(value)
731                     || "Y".equalsIgnoreCase(value)) {
732                 throw new AaiException("is-closed-loop-disabled is set to true (query by vserver-name)");
733             }
734         }
735     }
736
737     /**
738      * Is closed loop disabled for an event.
739      * 
740      * @param event the event
741      * @return <code>true</code> if the contol loop is disabled, <code>false</code> otherwise
742      */
743     public static boolean isClosedLoopDisabled(VirtualControlLoopEvent event) {
744         if ("true".equalsIgnoreCase(event.getAai().get(VSERVER_IS_CLOSED_LOOP_DISABLED))
745                 || "T".equalsIgnoreCase(event.getAai().get(VSERVER_IS_CLOSED_LOOP_DISABLED))
746                 || "yes".equalsIgnoreCase(event.getAai().get(VSERVER_IS_CLOSED_LOOP_DISABLED))
747                 || "Y".equalsIgnoreCase(event.getAai().get(VSERVER_IS_CLOSED_LOOP_DISABLED))) {
748             return true;
749         }
750         return ("true".equalsIgnoreCase(event.getAai().get(GENERIC_VNF_IS_CLOSED_LOOP_DISABLED))
751                 || "T".equalsIgnoreCase(event.getAai().get(GENERIC_VNF_IS_CLOSED_LOOP_DISABLED))
752                 || "yes".equalsIgnoreCase(event.getAai().get(GENERIC_VNF_IS_CLOSED_LOOP_DISABLED))
753                 || "Y".equalsIgnoreCase(event.getAai().get(GENERIC_VNF_IS_CLOSED_LOOP_DISABLED)));
754     }
755
756     /**
757      * Get the A&AI VService information for an event.
758      * 
759      * @param event the event
760      * @return a AaiGetVserverResponse
761      * @throws ControlLoopException if an error occurs
762      */
763     public static AaiGetVserverResponse getAAIVserverInfo(VirtualControlLoopEvent event) throws ControlLoopException {
764         UUID requestId = event.getRequestId();
765         AaiGetVserverResponse response = null;
766         String vserverName = event.getAai().get(VSERVER_VSERVER_NAME);
767
768         try {
769             if (vserverName != null) {
770                 String aaiHostURL = PolicyEngine.manager.getEnvironmentProperty("aai.url");
771                 String aaiUser = PolicyEngine.manager.getEnvironmentProperty("aai.username");
772                 String aaiPassword = PolicyEngine.manager.getEnvironmentProperty("aai.password");
773                 String aaiGetQueryByVserver = "/aai/v11/nodes/vservers?vserver-name=";
774                 String url = aaiHostURL + aaiGetQueryByVserver;
775                 logger.info("AAI Host URL by VServer: {}", url);
776                 response = new AaiManager(new RESTManager()).getQueryByVserverName(url, aaiUser, aaiPassword, requestId,
777                         vserverName);
778             }
779         } catch (Exception e) {
780             logger.error("getAAIVserverInfo exception: ", e);
781             throw new ControlLoopException("Exception in getAAIVserverInfo: ", e);
782         }
783
784         return response;
785     }
786
787     /**
788      * Get A&AI VNF information for an event.
789      * 
790      * @param event the event
791      * @return a AaiGetVnfResponse
792      * @throws ControlLoopException if an error occurs
793      */
794     public static AaiGetVnfResponse getAAIVnfInfo(VirtualControlLoopEvent event) throws ControlLoopException {
795         UUID requestId = event.getRequestId();
796         AaiGetVnfResponse response = null;
797         String vnfName = event.getAai().get(GENERIC_VNF_VNF_NAME);
798         String vnfId = event.getAai().get(GENERIC_VNF_VNF_ID);
799
800         String aaiHostURL = PolicyEngine.manager.getEnvironmentProperty("aai.url");
801         String aaiUser = PolicyEngine.manager.getEnvironmentProperty("aai.username");
802         String aaiPassword = PolicyEngine.manager.getEnvironmentProperty("aai.password");
803
804         try {
805             if (vnfName != null) {
806                 String aaiGetQueryByVnfName = "/aai/v11/network/generic-vnfs/generic-vnf?vnf-name=";
807                 String url = aaiHostURL + aaiGetQueryByVnfName;
808                 logger.info("AAI Host URL by VNF name: {}", url);
809                 response = new AaiManager(new RESTManager()).getQueryByVnfName(url, aaiUser, aaiPassword, requestId,
810                         vnfName);
811             } else if (vnfId != null) {
812                 String aaiGetQueryByVnfId = "/aai/v11/network/generic-vnfs/generic-vnf/";
813                 String url = aaiHostURL + aaiGetQueryByVnfId;
814                 logger.info("AAI Host URL by VNF ID: {}", url);
815                 response =
816                         new AaiManager(new RESTManager()).getQueryByVnfId(url, aaiUser, aaiPassword, requestId, vnfId);
817             }
818         } catch (Exception e) {
819             logger.error("getAAIVnfInfo exception: ", e);
820             throw new ControlLoopException("Exception in getAAIVnfInfo: ", e);
821         }
822
823         return response;
824     }
825
826     @Override
827     public boolean isActive() {
828         // TODO
829         return true;
830     }
831
832     @Override
833     public boolean releaseLock() {
834         // TODO
835         return false;
836     }
837
838     @Override
839     public String toString() {
840         return "ControlLoopEventManager [closedLoopControlName=" + closedLoopControlName + ", requestID=" + requestID
841                 + ", processor=" + processor + ", onset=" + (onset != null ? onset.getRequestId() : "null")
842                 + ", numOnsets=" + numOnsets + ", numAbatements=" + numAbatements + ", isActivated=" + isActivated
843                 + ", currentOperation=" + currentOperation + ", targetLock=" + targetLock + "]";
844     }
845
846 }