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