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