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