Merge 'origin/casablanca' into master
[so.git] / asdc-controller / src / main / java / org / onap / so / asdc / client / ASDCController.java
1 /*-
2 d * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * Copyright (C) 2017 Huawei Technologies Co., Ltd. All rights reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.so.asdc.client;
23
24
25 import java.io.File;
26 import java.io.FileOutputStream;
27 import java.io.IOException;
28 import java.io.UnsupportedEncodingException;
29 import java.nio.file.Paths;
30 import java.util.List;
31
32 import org.onap.sdc.api.IDistributionClient;
33 import org.onap.sdc.api.consumer.IDistributionStatusMessage;
34 import org.onap.sdc.api.consumer.IFinalDistrStatusMessage;
35 import org.onap.sdc.api.notification.IArtifactInfo;
36 import org.onap.sdc.api.notification.INotificationData;
37 import org.onap.sdc.api.notification.IResourceInstance;
38 import org.onap.sdc.api.results.IDistributionClientDownloadResult;
39 import org.onap.sdc.api.results.IDistributionClientResult;
40 import org.onap.sdc.impl.DistributionClientFactory;
41 import org.onap.sdc.utils.DistributionActionResultEnum;
42 import org.onap.sdc.utils.DistributionStatusEnum;
43 import org.onap.so.asdc.client.exceptions.ASDCControllerException;
44 import org.onap.so.asdc.client.exceptions.ASDCDownloadException;
45 import org.onap.so.asdc.client.exceptions.ASDCParametersException;
46 import org.onap.so.asdc.client.exceptions.ArtifactInstallerException;
47 import org.onap.so.asdc.installer.IVfResourceInstaller;
48 import org.onap.so.asdc.installer.ToscaResourceStructure;
49 import org.onap.so.asdc.installer.VfResourceStructure;
50 import org.onap.so.asdc.installer.bpmn.BpmnInstaller;
51 import org.onap.so.asdc.installer.heat.ToscaResourceInstaller;
52 import org.onap.so.asdc.tenantIsolation.DistributionStatus;
53 import org.onap.so.asdc.tenantIsolation.WatchdogDistribution;
54 import org.onap.so.asdc.util.ASDCNotificationLogging;
55 import org.onap.so.db.request.beans.WatchdogDistributionStatus;
56 import org.onap.so.db.request.data.repository.WatchdogDistributionStatusRepository;
57 import org.onap.so.logger.MessageEnum;
58
59 import org.onap.so.logger.MsoLogger;
60 import org.springframework.beans.factory.annotation.Autowired;
61 import org.springframework.stereotype.Component;
62
63 @Component
64 public class ASDCController {
65
66     protected static final MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.ASDC,ASDCController.class);
67
68
69
70     protected boolean isAsdcClientAutoManaged = false;
71
72     protected String controllerName;
73     
74     private ASDCControllerStatus controllerStatus = ASDCControllerStatus.STOPPED;
75     
76     protected int nbOfNotificationsOngoing = 0;
77
78     @Autowired
79     private ToscaResourceInstaller toscaInstaller;
80     
81     @Autowired
82     private BpmnInstaller bpmnInstaller;
83     
84     @Autowired
85     private WatchdogDistributionStatusRepository wdsRepo;
86     
87     @Autowired
88     private ASDCConfiguration asdcConfig;
89     
90     @Autowired
91     private ASDCStatusCallBack asdcStatusCallBack;
92     
93     @Autowired
94     private ASDCNotificationCallBack asdcNotificationCallBack;
95     
96     private IDistributionClient distributionClient;
97     
98     private static final String UUID_PARAM = "(UUID:";
99     
100     @Autowired
101     private WatchdogDistribution wd;
102    
103
104     public int getNbOfNotificationsOngoing () {
105         return nbOfNotificationsOngoing;
106     }    
107
108     public IDistributionClient getDistributionClient() {
109                 return distributionClient;
110         }
111
112
113
114         public void setDistributionClient(IDistributionClient distributionClient) {
115                 this.distributionClient = distributionClient;
116         }
117
118
119
120         protected void changeControllerStatus (ASDCControllerStatus newControllerStatus) {
121         switch (newControllerStatus) {
122
123             case BUSY:
124                 ++this.nbOfNotificationsOngoing;
125                 this.controllerStatus = newControllerStatus;
126                 break;
127
128             case IDLE:
129                 if (this.nbOfNotificationsOngoing > 1) {
130                     --this.nbOfNotificationsOngoing;
131                 } else {
132                     this.nbOfNotificationsOngoing = 0;
133                     this.controllerStatus = newControllerStatus;
134                 }
135
136                 break;
137             default:
138                 this.controllerStatus = newControllerStatus;
139                 break;
140
141         }
142     }
143
144     public ASDCControllerStatus getControllerStatus () {
145         return this.controllerStatus;
146     }
147     
148     public ASDCController () {
149         isAsdcClientAutoManaged = true;        
150     }
151
152     public ASDCController (String controllerConfigName) {
153         isAsdcClientAutoManaged = true;
154         this.controllerName = controllerConfigName;
155     }
156
157     public ASDCController (String controllerConfigName, IDistributionClient asdcClient, IVfResourceInstaller resourceinstaller) {
158         distributionClient = asdcClient;       
159     }
160
161     public ASDCController (String controllerConfigName,IDistributionClient asdcClient) {
162         distributionClient = asdcClient;
163         this.controllerName = controllerConfigName;     
164     }
165     public String getControllerName() {
166                 return controllerName;
167         }
168
169         public void setControllerName(String controllerName) {
170                 this.controllerName = controllerName;
171         }
172
173         /**
174      * This method initializes the ASDC Controller and the ASDC Client.
175      *
176      * @throws ASDCControllerException It throws an exception if the ASDC Client cannot be instantiated or if an init
177      *         attempt is done when already initialized
178      * @throws ASDCParametersException If there is an issue with the parameters provided
179      * @throws IOException In case of issues when trying to load the key file
180      */
181     public void initASDC () throws ASDCControllerException {
182         String event = "Initialize the ASDC Controller";
183         MsoLogger.setServiceName ("InitASDC");
184         LOGGER.debug (event);
185         if (this.getControllerStatus () != ASDCControllerStatus.STOPPED) {
186             String endEvent = "The controller is already initialized, call the closeASDC method first";
187             throw new ASDCControllerException (endEvent);
188         }
189
190         if (asdcConfig != null) {          
191             asdcConfig.setAsdcControllerName(controllerName);
192         }    
193
194         if (this.distributionClient == null) {
195             distributionClient = DistributionClientFactory.createDistributionClient ();
196         }
197         
198         long initStartTime = System.currentTimeMillis ();
199         IDistributionClientResult result = this.distributionClient.init (asdcConfig,
200                                                                          asdcNotificationCallBack, asdcStatusCallBack);
201         if (!result.getDistributionActionResult ().equals (DistributionActionResultEnum.SUCCESS)) {
202             String endEvent = "ASDC distribution client init failed with reason:"
203                               + result.getDistributionMessageResult ();
204             LOGGER.recordMetricEvent (initStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.UnknownError, "Initialization of the ASDC Controller failed with reason:" + result.getDistributionMessageResult (), "ASDC", "init", null);
205             LOGGER.debug (endEvent);
206             this.changeControllerStatus (ASDCControllerStatus.STOPPED);
207             throw new ASDCControllerException ("Initialization of the ASDC Controller failed with reason: "
208                                                + result.getDistributionMessageResult ());
209         }
210         LOGGER.recordMetricEvent (initStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully initialize ASDC Controller", "ASDC", "init", null);
211
212         long clientstartStartTime = System.currentTimeMillis ();
213         result = this.distributionClient.start ();
214         if (!result.getDistributionActionResult ().equals (DistributionActionResultEnum.SUCCESS)) {
215             String endEvent = "ASDC distribution client start failed with reason:"
216                               + result.getDistributionMessageResult ();
217             LOGGER.recordMetricEvent (clientstartStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.UnknownError, endEvent, "ASDC", "start", null);
218             LOGGER.debug (endEvent);           
219             this.changeControllerStatus (ASDCControllerStatus.STOPPED);
220             throw new ASDCControllerException ("Startup of the ASDC Controller failed with reason: "
221                                                + result.getDistributionMessageResult ());
222         }
223         LOGGER.recordMetricEvent (clientstartStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully start ASDC distribution client", "ASDC", "start", null);
224
225
226         this.changeControllerStatus (ASDCControllerStatus.IDLE);
227         LOGGER.info (MessageEnum.ASDC_INIT_ASDC_CLIENT_SUC, "ASDC", "changeControllerStatus","");
228     }
229
230     /**
231      * This method closes the ASDC Controller and the ASDC Client.
232      *
233      * @throws ASDCControllerException It throws an exception if the ASDC Client cannot be closed because
234      *         it's currently BUSY in processing notifications.
235      */
236     public void closeASDC () throws ASDCControllerException {
237
238         MsoLogger.setServiceName ("CloseController");
239         if (this.getControllerStatus () == ASDCControllerStatus.BUSY) {
240             throw new ASDCControllerException ("Cannot close the ASDC controller as it's currently in BUSY state");
241         }
242         if (this.distributionClient != null) {
243             this.distributionClient.stop ();
244             // If auto managed we can set it to Null, ASDCController controls it.
245             // In the other case the client of this class has specified it, so we can't reset it
246             if (isAsdcClientAutoManaged) {
247                 // Next init will initialize it with a new ASDC Client
248                 this.distributionClient = null;
249             }
250
251         }
252         this.changeControllerStatus (ASDCControllerStatus.STOPPED);
253     }
254
255     private boolean checkResourceAlreadyDeployed (VfResourceStructure resource) throws ArtifactInstallerException {
256
257         
258                 if (toscaInstaller.isResourceAlreadyDeployed (resource)) {
259                         LOGGER.info (MessageEnum.ASDC_ARTIFACT_ALREADY_EXIST,
260                     resource.getResourceInstance().getResourceInstanceName(),
261                     resource.getResourceInstance().getResourceUUID(),
262                     resource.getResourceInstance().getResourceName(), "", "");
263
264                         this.sendDeployNotificationsForResource(resource,DistributionStatusEnum.ALREADY_DOWNLOADED,null);
265                         this.sendDeployNotificationsForResource(resource,DistributionStatusEnum.ALREADY_DEPLOYED,null);
266
267                 return true;
268         } else {
269                 return false;
270         }
271     }
272
273    
274
275     protected IDistributionClientDownloadResult downloadTheArtifact (IArtifactInfo artifact,
276                                                                    String distributionId) throws ASDCDownloadException {
277
278         LOGGER.debug ("Trying to download the artifact : " + artifact.getArtifactURL ()
279                       + UUID_PARAM
280                       + artifact.getArtifactUUID ()
281                       + ")");
282         IDistributionClientDownloadResult downloadResult;
283
284
285         try {
286             downloadResult = distributionClient.download (artifact);
287             if (null == downloadResult) {
288                 LOGGER.info (MessageEnum.ASDC_ARTIFACT_NULL, artifact.getArtifactUUID (), "", "");
289                 return downloadResult;
290             }
291         } catch (RuntimeException e) {
292             LOGGER.debug ("Not able to download the artifact due to an exception: " + artifact.getArtifactURL ());
293             this.sendASDCNotification (NotificationType.DOWNLOAD,
294                                        artifact.getArtifactURL (),
295                                        asdcConfig.getConsumerID (),
296                                        distributionId,
297                                        DistributionStatusEnum.DOWNLOAD_ERROR,
298                                        e.getMessage (),
299                                        System.currentTimeMillis ());
300
301             throw new ASDCDownloadException ("Exception caught when downloading the artifact", e);
302         }
303
304         if (DistributionActionResultEnum.SUCCESS.equals(downloadResult.getDistributionActionResult ())) {
305
306             LOGGER.info (MessageEnum.ASDC_ARTIFACT_DOWNLOAD_SUC,
307                          artifact.getArtifactURL (),
308                          artifact.getArtifactUUID (),
309                          String.valueOf (downloadResult.getArtifactPayload ().length), "", "");
310
311         } else {
312
313             LOGGER.error (MessageEnum.ASDC_ARTIFACT_DOWNLOAD_FAIL,
314                           artifact.getArtifactName (),
315                           artifact.getArtifactURL (),
316                           artifact.getArtifactUUID (),
317                           downloadResult.getDistributionMessageResult (), "", "", MsoLogger.ErrorCode.DataError, "ASDC artifact download fail");
318
319             this.sendASDCNotification (NotificationType.DOWNLOAD,
320                                        artifact.getArtifactURL (),
321                                        asdcConfig.getConsumerID (),
322                                        distributionId,
323                                        DistributionStatusEnum.DOWNLOAD_ERROR,
324                                        downloadResult.getDistributionMessageResult (),
325                                        System.currentTimeMillis ());
326
327             throw new ASDCDownloadException ("Artifact " + artifact.getArtifactName ()
328                                              + " could not be downloaded from ASDC URL "
329                                              + artifact.getArtifactURL ()
330                                              + UUID_PARAM
331                                              + artifact.getArtifactUUID ()
332                                              + ")"
333                                              + System.lineSeparator ()
334                                              + "Error message is "
335                                              + downloadResult.getDistributionMessageResult ()
336                                              + System.lineSeparator ());
337
338         }
339
340         this.sendASDCNotification (NotificationType.DOWNLOAD,
341                                    artifact.getArtifactURL (),
342                                    asdcConfig.getConsumerID (),
343                                    distributionId,
344                                    DistributionStatusEnum.DOWNLOAD_OK,
345                                    null,
346                                    System.currentTimeMillis ());
347         return downloadResult;
348
349     }
350
351     private void writeArtifactToFile (IArtifactInfo artifact,
352                 IDistributionClientDownloadResult resultArtifact) {
353
354         LOGGER.debug ("Trying to write artifact to file : " + artifact.getArtifactURL ()
355                         + UUID_PARAM
356                         + artifact.getArtifactUUID ()
357                         + ")");
358         
359         String filePath = Paths.get(System.getProperty("mso.config.path"), "ASDC",  artifact.getArtifactVersion(), artifact.getArtifactName()).normalize().toString();
360         // make parent directory
361         File file = new File(filePath);         
362         File fileParent = file.getParentFile();
363         if (!fileParent.exists()) {
364             fileParent.mkdirs();
365         }
366
367         byte[] payloadBytes = resultArtifact.getArtifactPayload();
368         
369         try (FileOutputStream outFile = new FileOutputStream(filePath)) {
370                 LOGGER.info(MessageEnum.ASDC_RECEIVE_SERVICE_NOTIF, "***WRITE FILE ARTIFACT NAME", "ASDC", artifact.getArtifactName());
371                 outFile.write(payloadBytes, 0, payloadBytes.length);
372                 outFile.close();
373         } catch (Exception e) { 
374                         LOGGER.debug("Exception :",e);
375             LOGGER.error(MessageEnum.ASDC_ARTIFACT_DOWNLOAD_FAIL,
376                                 artifact.getArtifactName (),
377                                 artifact.getArtifactURL (),
378                                 artifact.getArtifactUUID (),
379                                 resultArtifact.getDistributionMessageResult (), "", "", MsoLogger.ErrorCode.DataError, "ASDC write to file failed"); 
380         } 
381         
382     }
383
384
385     protected void sendDeployNotificationsForResource(VfResourceStructure vfResourceStructure,DistributionStatusEnum distribStatus, String errorReason) {
386
387         for (IArtifactInfo artifactInfo : vfResourceStructure.getResourceInstance().getArtifacts()) {
388
389                 if ((DistributionStatusEnum.DEPLOY_OK.equals(distribStatus) && !artifactInfo.getArtifactType().equalsIgnoreCase("OTHER") && !vfResourceStructure.isAlreadyDeployed())
390                                 // This could be NULL if the artifact is a VF module artifact, this won't be present in the MAP
391                                 && vfResourceStructure.getArtifactsMapByUUID().get(artifactInfo.getArtifactUUID()) != null
392                                 && vfResourceStructure.getArtifactsMapByUUID().get(artifactInfo.getArtifactUUID()).getDeployedInDb() == 0) {
393                         this.sendASDCNotification (NotificationType.DEPLOY,
394                                         artifactInfo.getArtifactURL (),
395                           asdcConfig.getConsumerID (),
396                           vfResourceStructure.getNotification().getDistributionID(),
397                           DistributionStatusEnum.DEPLOY_ERROR,
398                           "The artifact has not been used by the modules defined in the resource",
399                           System.currentTimeMillis ());
400                 } else {
401                         this.sendASDCNotification (NotificationType.DEPLOY,
402                                         artifactInfo.getArtifactURL (),
403                           asdcConfig.getConsumerID (),
404                           vfResourceStructure.getNotification().getDistributionID(),
405                           distribStatus,
406                           errorReason,
407                           System.currentTimeMillis ());
408                 }
409         }
410     }
411     
412     protected void sendCsarDeployNotification(INotificationData iNotif, VfResourceStructure resourceStructure, ToscaResourceStructure toscaResourceStructure, boolean deploySuccessful, String errorReason) {
413         
414                 IArtifactInfo csarArtifact = toscaResourceStructure.getToscaArtifact();
415                 
416                 if(deploySuccessful){
417                         
418                 this.sendASDCNotification (NotificationType.DEPLOY,
419                                   csarArtifact.getArtifactURL (),
420                           asdcConfig.getConsumerID (),
421                           resourceStructure.getNotification().getDistributionID(),
422                           DistributionStatusEnum.DEPLOY_OK,
423                           errorReason,
424                           System.currentTimeMillis ());
425                         
426                 } else {
427                         
428                         this.sendASDCNotification (NotificationType.DEPLOY,
429                           csarArtifact.getArtifactURL (),
430                   asdcConfig.getConsumerID (),
431                   resourceStructure.getNotification().getDistributionID(),
432                   DistributionStatusEnum.DEPLOY_ERROR,
433                   errorReason,
434                   System.currentTimeMillis ());
435                         
436                 }
437     }
438     
439     protected void deployResourceStructure (VfResourceStructure resourceStructure, ToscaResourceStructure toscaResourceStructure) throws ArtifactInstallerException {
440
441         LOGGER.info (MessageEnum.ASDC_START_DEPLOY_ARTIFACT, resourceStructure.getResourceInstance().getResourceInstanceName(), resourceStructure.getResourceInstance().getResourceUUID(), "ASDC");
442         try {
443                 String resourceType = resourceStructure.getResourceInstance().getResourceType();
444                 String category = resourceStructure.getResourceInstance().getCategory();
445                 if("VF".equals(resourceType) && !"Allotted Resource".equalsIgnoreCase(category)){
446                         resourceStructure.createVfModuleStructures();
447                 }
448                 toscaInstaller.installTheResource(toscaResourceStructure, resourceStructure);                                                   
449
450         } catch (ArtifactInstallerException e) {
451                 LOGGER.info (MessageEnum.ASDC_ARTIFACT_DOWNLOAD_FAIL,
452                                 resourceStructure.getResourceInstance().getResourceName(),
453                                 resourceStructure.getResourceInstance().getResourceUUID(),
454                         String.valueOf (resourceStructure.getVfModuleStructure().size()), "ASDC", "deployResourceStructure");
455                 sendDeployNotificationsForResource(resourceStructure,DistributionStatusEnum.DEPLOY_ERROR,e.getMessage());
456                 throw e;
457         }
458
459         if (resourceStructure.isDeployedSuccessfully() || toscaResourceStructure.isDeployedSuccessfully()) {
460                 LOGGER.info (MessageEnum.ASDC_ARTIFACT_DEPLOY_SUC,
461                                 resourceStructure.getResourceInstance().getResourceName(),
462                                 resourceStructure.getResourceInstance().getResourceUUID(),
463                         String.valueOf (resourceStructure.getVfModuleStructure().size()), "ASDC", "deployResourceStructure");
464                 sendDeployNotificationsForResource(resourceStructure,DistributionStatusEnum.DEPLOY_OK ,null);
465         }
466
467     }
468     
469
470     private enum NotificationType {
471         DOWNLOAD, DEPLOY
472     }
473
474     protected void sendASDCNotification (NotificationType notificationType,
475                                        String artifactURL,
476                                        String consumerID,
477                                        String distributionID,
478                                        DistributionStatusEnum status,
479                                        String errorReason,
480                                        long timestamp) {
481
482         String event = "Sending " + notificationType.name ()
483                        + "("
484                        + status.name ()
485                        + ")"
486                        + " notification to ASDC for artifact:"
487                        + artifactURL;
488
489         if (errorReason != null) {
490                 event=event+"("+errorReason+")";
491         }
492         LOGGER.info (MessageEnum.ASDC_SEND_NOTIF_ASDC, notificationType.name (), status.name (), artifactURL, "ASDC", "sendASDCNotification");
493         LOGGER.debug (event);
494
495         long subStarttime = System.currentTimeMillis ();
496         String action = "";
497         try {
498             IDistributionStatusMessage message = new DistributionStatusMessage (artifactURL,
499                                                                                 consumerID,
500                                                                                 distributionID,
501                                                                                 status,
502                                                                                 timestamp);
503
504             switch (notificationType) {
505                 case DOWNLOAD:
506                     if (errorReason != null) {
507                         this.distributionClient.sendDownloadStatus (message, errorReason);
508                     } else {
509                         this.distributionClient.sendDownloadStatus (message);
510                     }
511                     action = "sendDownloadStatus";
512                     break;
513                 case DEPLOY:
514                     if (errorReason != null) {
515                         this.distributionClient.sendDeploymentStatus (message, errorReason);
516                     } else {
517                         this.distributionClient.sendDeploymentStatus (message);
518                     }
519                     action = "sendDeploymentdStatus";
520                     break;
521                 default:
522                         break;
523             }
524         } catch (RuntimeException e) {           
525             LOGGER.warn (MessageEnum.ASDC_SEND_NOTIF_ASDC_EXEC, "ASDC", "sendASDCNotification", MsoLogger.ErrorCode.SchemaError, "RuntimeException - sendASDCNotification", e);
526         }
527         LOGGER.recordMetricEvent (subStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully sent notification to ASDC", "ASDC", action, null);
528     }
529     
530     protected void sendFinalDistributionStatus (
531                 String distributionID,
532                 DistributionStatusEnum status,
533                 String errorReason) {
534
535
536         LOGGER.debug ("Enter sendFinalDistributionStatus with DistributionID " + distributionID + " and Status of " + status.name() + " and ErrorReason " + errorReason);
537
538         long subStarttime = System.currentTimeMillis ();
539         try {
540                 
541                 
542                 IFinalDistrStatusMessage finalDistribution = new FinalDistributionStatusMessage(distributionID,status,subStarttime, asdcConfig.getConsumerID());
543                 
544                 if(errorReason == null){
545                         this.distributionClient.sendFinalDistrStatus(finalDistribution);
546                 }else{
547                         this.distributionClient.sendFinalDistrStatus(finalDistribution, errorReason);
548                 }
549                 
550  
551         } catch (RuntimeException e) {                  
552                 LOGGER.debug ("Exception caught in sendFinalDistributionStatus " + e.getMessage());
553                 LOGGER.warn (MessageEnum.ASDC_SEND_NOTIF_ASDC_EXEC, "ASDC", "sendASDCNotification", MsoLogger.ErrorCode.SchemaError, "RuntimeException - sendASDCNotification", e);
554         }
555         LOGGER.recordMetricEvent (subStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully sent Final notification to ASDC", "ASDC", null, null);
556     }
557
558     public void treatNotification (INotificationData iNotif) {
559
560         int noOfArtifacts = 0;
561         
562
563         for (IResourceInstance resource : iNotif.getResources ()) {
564                 noOfArtifacts += resource.getArtifacts ().size ();
565         }
566         LOGGER.info (MessageEnum.ASDC_RECEIVE_CALLBACK_NOTIF,
567                      String.valueOf (noOfArtifacts),
568                      iNotif.getServiceUUID (), "ASDC");
569
570         try {
571                 LOGGER.debug(ASDCNotificationLogging.dumpASDCNotification(iNotif));
572                         LOGGER.info(MessageEnum.ASDC_RECEIVE_SERVICE_NOTIF, iNotif.getServiceUUID(), "ASDC", "treatNotification");
573                         this.changeControllerStatus(ASDCControllerStatus.BUSY);
574                         toscaInstaller.processWatchdog(iNotif.getDistributionID(),iNotif.getServiceUUID());     
575                         
576                         // Process only the Resource artifacts in MSO                           
577                         this.processResourceNotification(iNotif);
578                         
579                         //********************************************************************************************************
580                         //Start Watchdog loop and wait for all components to complete before reporting final status back. 
581                         // **If timer expires first then we will report a Distribution Error back to ASDC
582                         //********************************************************************************************************
583                 long initialStartTime = System.currentTimeMillis();
584                 boolean componentsComplete = false;
585                 String distributionStatus = null;
586                 String watchdogError = null;
587                 String overallStatus = null;
588                 int watchDogTimeout = asdcConfig.getWatchDogTimeout() * 1000;
589                 boolean isDeploySuccess = false;                
590                                                 
591                 while(!componentsComplete && (System.currentTimeMillis() - initialStartTime) < watchDogTimeout)
592                 {
593                                                 
594                         try{                    
595                                 distributionStatus = wd.getOverallDistributionStatus(iNotif.getDistributionID());
596                                 Thread.sleep(watchDogTimeout / 10);             
597                         }catch(Exception e){
598                                 LOGGER.debug ("Exception in Watchdog Loop " + e);
599                                 Thread.sleep(watchDogTimeout / 10);
600                         }
601                         
602                         if(distributionStatus != null && !distributionStatus.equalsIgnoreCase(DistributionStatus.INCOMPLETE.name())){
603                                 
604                                 if(distributionStatus.equalsIgnoreCase(DistributionStatus.SUCCESS.name())){
605                                         isDeploySuccess = true;
606                                         overallStatus = DistributionStatusEnum.DISTRIBUTION_COMPLETE_OK.name();
607                                 }else{
608                                         overallStatus = DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name();
609                                 }                               
610                                 componentsComplete = true;
611                         }
612                 }
613                 
614                 if(!componentsComplete){
615                         LOGGER.debug("Timeout of " + watchDogTimeout + " seconds was reached before all components reported status");
616                         watchdogError = "Timeout occurred while waiting for all components to report status";
617                         overallStatus = DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name();
618                 }
619                 
620                 if(distributionStatus == null){         
621                         overallStatus = DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name();
622                         LOGGER.debug("DistributionStatus is null for DistributionId: " + iNotif.getDistributionID());                           
623                 }
624                 
625                 try {
626                         wd.executePatchAAI(iNotif.getDistributionID(), iNotif.getServiceInvariantUUID(), overallStatus);
627                         LOGGER.debug ("A&AI Updated succefully with Distribution Status!");
628                 }
629                 catch(Exception e) {
630                         LOGGER.debug ("Exception in Watchdog executePatchAAI(): " + e);
631                         watchdogError = "Error calling A&AI " + e.getMessage();
632                         if(e.getCause() != null) {
633                                 LOGGER.debug ("Exception caused by: " + e.getCause().getMessage());
634                         }
635                 }
636         
637                 
638                 if(isDeploySuccess && watchdogError == null){
639                         sendFinalDistributionStatus(iNotif.getDistributionID(), DistributionStatusEnum.DISTRIBUTION_COMPLETE_OK, null);
640                         WatchdogDistributionStatus wds = new WatchdogDistributionStatus(iNotif.getDistributionID());
641                         wds.setDistributionIdStatus(DistributionStatusEnum.DISTRIBUTION_COMPLETE_OK.toString());
642                         wdsRepo.save(wds);
643                 } else {
644                         sendFinalDistributionStatus(iNotif.getDistributionID(), DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR, watchdogError);
645                         WatchdogDistributionStatus wds = new WatchdogDistributionStatus(iNotif.getDistributionID());
646                         wds.setDistributionIdStatus(DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.toString());
647                         wdsRepo.save(wds);
648                 }
649                 
650                 
651
652         } catch (Exception e) {
653             LOGGER.error (MessageEnum.ASDC_GENERAL_EXCEPTION_ARG,
654                           "Unexpected exception caught during the notification processing",  "ASDC", "treatNotification", MsoLogger.ErrorCode.SchemaError, "RuntimeException in treatNotification",
655                           e);
656             
657                 try {
658                         wd.executePatchAAI(iNotif.getDistributionID(), iNotif.getServiceInvariantUUID(), DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name());
659                         LOGGER.debug ("A&AI Updated succefully with Distribution Status of " + DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name());
660                 }
661                 catch(Exception aaiException) {
662                         LOGGER.debug ("Exception in executePatchAAI(): " + aaiException);
663                         if(aaiException.getCause() != null) {
664                                 LOGGER.debug ("Exception caused by: " + aaiException.getCause().getMessage());
665                         }
666                 }
667             
668              sendFinalDistributionStatus(iNotif.getDistributionID(), DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR, e.getMessage());
669              
670                  WatchdogDistributionStatus wds = new WatchdogDistributionStatus(iNotif.getDistributionID());
671                  wds.setDistributionIdStatus(DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.toString());
672                  wdsRepo.save(wds);
673             
674         } finally {
675             this.changeControllerStatus (ASDCControllerStatus.IDLE);
676         }
677     }
678
679     protected void processResourceNotification (INotificationData iNotif) {
680         // For each artifact, create a structure describing the VFModule in a ordered flat level
681         VfResourceStructure resourceStructure = null;
682         ToscaResourceStructure toscaResourceStructure = new ToscaResourceStructure();
683         boolean deploySuccessful = true;
684         boolean hasVFResource = false;
685         String errorMessage = null;
686
687         try {
688                 
689                         this.processCsarServiceArtifacts(iNotif, toscaResourceStructure);
690                         IArtifactInfo iArtifact = toscaResourceStructure.getToscaArtifact();
691                         String filePath = System.getProperty("mso.config.path") + "/ASDC/" + iArtifact.getArtifactVersion() + "/" + iArtifact.getArtifactName();
692                         File csarFile = new File(filePath);
693                         String csarFilePath = csarFile.getAbsolutePath();
694                         if (bpmnInstaller.containsWorkflows(csarFilePath)) {
695                                 bpmnInstaller.installBpmn(csarFilePath);
696                         }                       
697                                                 
698                 for (IResourceInstance resource : iNotif.getResources()){
699                         
700                         resourceStructure = new VfResourceStructure(iNotif,resource);
701                         
702                         String resourceType = resourceStructure.getResourceInstance().getResourceType();
703                 String category = resourceStructure.getResourceInstance().getCategory();
704                                         
705                 LOGGER.debug("Processing Resource Type: " + resourceType + " and Model UUID: " + resourceStructure.getResourceInstance().getResourceUUID());
706                         
707                                 if("VF".equals(resourceType) && !"Allotted Resource".equalsIgnoreCase(category)){
708                                         
709                                         hasVFResource = true;
710                         
711                                 for (IArtifactInfo artifact : resource.getArtifacts()) {
712                                         IDistributionClientDownloadResult resultArtifact = this.downloadTheArtifact(artifact,
713                                                         iNotif.getDistributionID());
714                                         if (resultArtifact != null) {
715                                                                                         
716                                                 if (ASDCConfiguration.VF_MODULES_METADATA.equals(artifact.getArtifactType())) {
717                                                         LOGGER.debug("VF_MODULE_ARTIFACT: "+new String(resultArtifact.getArtifactPayload(),"UTF-8"));
718                                                         LOGGER.debug(ASDCNotificationLogging.dumpVfModuleMetaDataList(resourceStructure.decodeVfModuleArtifact(resultArtifact.getArtifactPayload())));
719                                                 }
720                                                 resourceStructure.addArtifactToStructure(distributionClient,artifact, resultArtifact);
721                                         }
722                                 }
723                                 
724                                         //Deploy VF resource and artifacts
725                                         LOGGER.debug("Preparing to deploy Service: " + iNotif.getServiceUUID());
726                                         try{
727                                                 
728                                                 this.deployResourceStructure(resourceStructure, toscaResourceStructure);
729
730                                         } catch(ArtifactInstallerException e){
731                                                 deploySuccessful = false;
732                                                 errorMessage = e.getMessage();
733                                                 LOGGER.error(e);
734                                         }  
735                                 }
736                                                 
737                 }       
738                 
739                         // There are cases where the Service has no VF resources, those are handled here
740                         if (!hasVFResource) {
741                                 
742                                 LOGGER.debug("No resources found for Service: " + iNotif.getServiceUUID());
743                                 
744                                 try{
745                                         resourceStructure = new VfResourceStructure(iNotif,new ResourceInstance()); 
746                                         
747                                         this.deployResourceStructure(resourceStructure, toscaResourceStructure);
748
749                                 } catch(ArtifactInstallerException e){
750                                         deploySuccessful = false;
751                                         errorMessage = e.getMessage();
752                                         LOGGER.error(e);
753                    }
754                 }
755                          this.sendCsarDeployNotification(iNotif, resourceStructure, toscaResourceStructure, deploySuccessful, errorMessage);
756                 
757         } catch (ASDCDownloadException | UnsupportedEncodingException e) {
758                 LOGGER.error(MessageEnum.ASDC_GENERAL_EXCEPTION_ARG,
759                                 "Exception caught during Installation of artifact", "ASDC", "processResourceNotification", MsoLogger.ErrorCode.BusinessProcesssError, "Exception in processResourceNotification", e);
760         }
761     }
762     protected void processCsarServiceArtifacts (INotificationData iNotif, ToscaResourceStructure toscaResourceStructure) {
763         
764         List<IArtifactInfo> serviceArtifacts = iNotif.getServiceArtifacts();
765         
766                 for(IArtifactInfo artifact : serviceArtifacts){
767                 
768                         if(artifact.getArtifactType().equals(ASDCConfiguration.TOSCA_CSAR)){
769                                 
770                                 try{
771                                         
772                                         toscaResourceStructure.setToscaArtifact(artifact);
773                                         
774                                         IDistributionClientDownloadResult resultArtifact = this.downloadTheArtifact(artifact,iNotif.getDistributionID());
775                                         
776                                         writeArtifactToFile(artifact, resultArtifact);
777                                         
778                                         toscaResourceStructure.updateResourceStructure(artifact);
779                                         
780                                         toscaResourceStructure.setServiceVersion(iNotif.getServiceVersion());
781                                         
782                                         LOGGER.debug(ASDCNotificationLogging.dumpCSARNotification(iNotif, toscaResourceStructure));
783                                         
784
785                                 } catch(Exception e){
786                                         LOGGER.error(MessageEnum.ASDC_GENERAL_EXCEPTION_ARG,
787                                                         "Exception caught during processCsarServiceArtifacts", "ASDC", "processCsarServiceArtifacts", MsoLogger.ErrorCode.BusinessProcesssError, "Exception in processCsarServiceArtifacts", e);
788                                 }
789                         }
790                         else if(artifact.getArtifactType().equals(ASDCConfiguration.WORKFLOWS)){
791                                 
792                                 try{                                    
793                                         
794                                         IDistributionClientDownloadResult resultArtifact = this.downloadTheArtifact(artifact,iNotif.getDistributionID());
795                                         
796                                         writeArtifactToFile(artifact, resultArtifact);
797                                         
798                                         toscaResourceStructure.setToscaArtifact(artifact);
799                                         
800                                         LOGGER.debug(ASDCNotificationLogging.dumpASDCNotification(iNotif));
801                                         
802
803                                 } catch(Exception e){
804                                         System.out.println("Whats the error " + e.getMessage());
805                                         LOGGER.error(MessageEnum.ASDC_GENERAL_EXCEPTION_ARG,
806                                                         "Exception caught during processCsarServiceArtifacts", "ASDC", "processCsarServiceArtifacts", MsoLogger.ErrorCode.BusinessProcesssError, "Exception in processCsarServiceArtifacts", e);
807                                 }
808                         }
809
810                                 
811                 }
812     }
813     
814     private static final String UNKNOWN="Unknown";
815     
816     /**
817      * @return the address of the ASDC we are connected to.
818      */
819     public String getAddress () {
820         if (asdcConfig != null) {
821             return asdcConfig.getAsdcAddress ();
822         }
823         return UNKNOWN;
824     }
825
826     /**
827      * @return the environment name of the ASDC we are connected to.
828      */
829     public String getEnvironment () {
830         if (asdcConfig != null) {
831             return asdcConfig.getEnvironmentName ();
832         }
833         return UNKNOWN;
834     }
835
836 }