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