2 * ============LICENSE_START=======================================================
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 * Modifications Copyright (c) 2020 Nokia
11 * ================================================================================
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
16 * http://www.apache.org/licenses/LICENSE-2.0
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 * ============LICENSE_END=========================================================
26 package org.onap.so.asdc.client;
29 import com.fasterxml.jackson.annotation.JsonInclude.Include;
30 import com.fasterxml.jackson.core.JsonProcessingException;
31 import com.fasterxml.jackson.databind.DeserializationFeature;
32 import com.fasterxml.jackson.databind.MapperFeature;
33 import com.fasterxml.jackson.databind.ObjectMapper;
35 import java.io.FileOutputStream;
36 import java.io.IOException;
37 import java.io.UnsupportedEncodingException;
38 import java.nio.charset.StandardCharsets;
39 import java.nio.file.Paths;
40 import java.util.List;
41 import java.util.Optional;
42 import org.onap.so.logger.LoggingAnchor;
43 import org.onap.logging.ref.slf4j.ONAPLogConstants;
44 import org.onap.sdc.api.IDistributionClient;
45 import org.onap.sdc.api.consumer.IDistributionStatusMessage;
46 import org.onap.sdc.api.consumer.IFinalDistrStatusMessage;
47 import org.onap.sdc.api.notification.IArtifactInfo;
48 import org.onap.sdc.api.notification.INotificationData;
49 import org.onap.sdc.api.notification.IResourceInstance;
50 import org.onap.sdc.api.results.IDistributionClientDownloadResult;
51 import org.onap.sdc.api.results.IDistributionClientResult;
52 import org.onap.sdc.impl.DistributionClientFactory;
53 import org.onap.sdc.utils.DistributionActionResultEnum;
54 import org.onap.sdc.utils.DistributionStatusEnum;
55 import org.onap.so.asdc.activity.DeployActivitySpecs;
56 import org.onap.so.asdc.client.exceptions.ASDCControllerException;
57 import org.onap.so.asdc.client.exceptions.ASDCDownloadException;
58 import org.onap.so.asdc.client.exceptions.ASDCParametersException;
59 import org.onap.so.asdc.client.exceptions.ArtifactInstallerException;
60 import org.onap.so.asdc.installer.IVfResourceInstaller;
61 import org.onap.so.asdc.installer.PnfResourceStructure;
62 import org.onap.so.asdc.installer.ResourceStructure;
63 import org.onap.so.asdc.installer.ResourceType;
64 import org.onap.so.asdc.installer.ToscaResourceStructure;
65 import org.onap.so.asdc.installer.VfResourceStructure;
66 import org.onap.so.asdc.installer.heat.ToscaResourceInstaller;
67 import org.onap.so.asdc.tenantIsolation.DistributionStatus;
68 import org.onap.so.asdc.tenantIsolation.WatchdogDistribution;
69 import org.onap.so.asdc.util.ASDCNotificationLogging;
70 import org.onap.so.db.request.beans.WatchdogComponentDistributionStatus;
71 import org.onap.so.db.request.beans.WatchdogDistributionStatus;
72 import org.onap.so.db.request.data.repository.WatchdogComponentDistributionStatusRepository;
73 import org.onap.so.db.request.data.repository.WatchdogDistributionStatusRepository;
74 import org.onap.so.logger.ErrorCode;
75 import org.onap.so.logger.MessageEnum;
76 import org.slf4j.Logger;
77 import org.slf4j.LoggerFactory;
79 import org.springframework.beans.factory.annotation.Autowired;
80 import org.springframework.orm.ObjectOptimisticLockingFailureException;
81 import org.springframework.stereotype.Component;
84 public class ASDCController {
86 protected static final Logger logger = LoggerFactory.getLogger(ASDCController.class);
88 private static final String UNKNOWN = "Unknown";
90 protected boolean isAsdcClientAutoManaged = false;
92 protected String controllerName;
94 private ASDCControllerStatus controllerStatus = ASDCControllerStatus.STOPPED;
96 protected int nbOfNotificationsOngoing = 0;
99 private ToscaResourceInstaller toscaInstaller;
102 private WatchdogDistributionStatusRepository wdsRepo;
105 protected WatchdogComponentDistributionStatusRepository watchdogCDStatusRepository;
108 private ASDCConfiguration asdcConfig;
111 private ASDCStatusCallBack asdcStatusCallBack;
114 private ASDCNotificationCallBack asdcNotificationCallBack;
116 private IDistributionClient distributionClient;
118 private static final String UUID_PARAM = "(UUID:";
120 protected static final String MSO = "SO";
123 private WatchdogDistribution wd;
126 DeployActivitySpecs deployActivitySpecs;
128 public ASDCController() {
132 public ASDCController(String controllerConfigName) {
133 isAsdcClientAutoManaged = true;
134 this.controllerName = controllerConfigName;
137 public ASDCController(String controllerConfigName, IDistributionClient asdcClient,
138 IVfResourceInstaller resourceinstaller) {
139 distributionClient = asdcClient;
142 public ASDCController(String controllerConfigName, IDistributionClient asdcClient) {
143 distributionClient = asdcClient;
144 this.controllerName = controllerConfigName;
147 public int getNbOfNotificationsOngoing() {
148 return nbOfNotificationsOngoing;
151 public IDistributionClient getDistributionClient() {
152 return distributionClient;
155 public void setDistributionClient(IDistributionClient distributionClient) {
156 this.distributionClient = distributionClient;
159 protected void changeControllerStatus(ASDCControllerStatus newControllerStatus) {
160 switch (newControllerStatus) {
163 ++this.nbOfNotificationsOngoing;
164 this.controllerStatus = newControllerStatus;
168 changeOnStatusIDLE(newControllerStatus);
172 this.controllerStatus = newControllerStatus;
178 private void changeOnStatusIDLE(ASDCControllerStatus newControllerStatus) {
179 if (this.nbOfNotificationsOngoing > 1) {
180 --this.nbOfNotificationsOngoing;
182 this.nbOfNotificationsOngoing = 0;
183 this.controllerStatus = newControllerStatus;
187 public ASDCControllerStatus getControllerStatus() {
188 return this.controllerStatus;
191 public String getControllerName() {
192 return controllerName;
195 public void setControllerName(String controllerName) {
196 this.controllerName = controllerName;
200 * This method initializes the ASDC Controller and the ASDC Client.
202 * @throws ASDCControllerException It throws an exception if the ASDC Client cannot be instantiated or if an init
203 * attempt is done when already initialized
204 * @throws ASDCParametersException If there is an issue with the parameters provided
205 * @throws IOException In case of issues when trying to load the key file
207 public void initASDC() throws ASDCControllerException {
208 logger.debug("Initialize the ASDC Controller");
210 throw new ASDCControllerException("The controller is already initialized, call the closeASDC method first");
213 if (asdcConfig != null) {
214 asdcConfig.setAsdcControllerName(controllerName);
217 if (this.distributionClient == null) {
218 distributionClient = DistributionClientFactory.createDistributionClient();
221 IDistributionClientResult result =
222 this.distributionClient.init(asdcConfig, asdcNotificationCallBack, asdcStatusCallBack);
223 if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
225 "ASDC distribution client init failed with reason:" + result.getDistributionMessageResult();
226 logger.debug(endEvent);
227 this.changeControllerStatus(ASDCControllerStatus.STOPPED);
228 throw new ASDCControllerException("Initialization of the ASDC Controller failed with reason: "
229 + result.getDistributionMessageResult());
232 result = this.distributionClient.start();
233 if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
235 "ASDC distribution client start failed with reason:" + result.getDistributionMessageResult();
236 logger.debug(endEvent);
237 this.changeControllerStatus(ASDCControllerStatus.STOPPED);
238 throw new ASDCControllerException(
239 "Startup of the ASDC Controller failed with reason: " + result.getDistributionMessageResult());
242 this.changeControllerStatus(ASDCControllerStatus.IDLE);
243 logger.info(LoggingAnchor.THREE, MessageEnum.ASDC_INIT_ASDC_CLIENT_SUC.toString(), "ASDC",
244 "changeControllerStatus");
248 * @return true if controller is stopped
250 public boolean isStopped() {
251 return this.getControllerStatus() == ASDCControllerStatus.STOPPED;
255 * This method closes the ASDC Controller and the ASDC Client.
257 * @throws ASDCControllerException It throws an exception if the ASDC Client cannot be closed because it's currently
258 * BUSY in processing notifications.
260 public void closeASDC() throws ASDCControllerException {
263 throw new ASDCControllerException("Cannot close the ASDC controller as it's currently in BUSY state");
265 if (this.distributionClient != null) {
266 this.distributionClient.stop();
267 // If auto managed we can set it to Null, ASDCController controls it.
268 // In the other case the client of this class has specified it, so we can't reset it
269 if (isAsdcClientAutoManaged) {
270 // Next init will initialize it with a new ASDC Client
271 this.distributionClient = null;
275 this.changeControllerStatus(ASDCControllerStatus.STOPPED);
279 * @return true if controller is currently processing notification
281 public boolean isBusy() {
282 return this.getControllerStatus() == ASDCControllerStatus.BUSY;
285 protected boolean checkResourceAlreadyDeployed(ResourceStructure resource, boolean serviceDeployed)
286 throws ArtifactInstallerException {
289 if (toscaInstaller.isResourceAlreadyDeployed(resource, serviceDeployed)) {
290 logger.info(LoggingAnchor.FOUR, MessageEnum.ASDC_ARTIFACT_ALREADY_EXIST.toString(),
291 resource.getResourceInstance().getResourceInstanceName(),
292 resource.getResourceInstance().getResourceUUID(), resource.getResourceInstance().getResourceName());
294 this.sendDeployNotificationsForResource(resource, DistributionStatusEnum.ALREADY_DOWNLOADED, null);
295 this.sendDeployNotificationsForResource(resource, DistributionStatusEnum.ALREADY_DEPLOYED, null);
303 protected void notifyErrorToAsdc(INotificationData iNotif, ToscaResourceStructure toscaResourceStructure,
304 DistributionStatusEnum deployStatus, VfResourceStructure resourceStructure, String errorMessage) {
305 // do csar lever first
306 this.sendCsarDeployNotification(resourceStructure, toscaResourceStructure, deployStatus, errorMessage);
308 for (IResourceInstance resource : iNotif.getResources()) {
309 resourceStructure = new VfResourceStructure(iNotif, resource);
310 errorMessage = String.format("Resource with UUID: %s already exists", resource.getResourceUUID());
311 this.sendCsarDeployNotification(resourceStructure, toscaResourceStructure, deployStatus, errorMessage);
315 protected boolean isCsarAlreadyDeployed(INotificationData iNotif, ToscaResourceStructure toscaResourceStructure) {
316 VfResourceStructure resourceStructure = null;
317 String errorMessage = "";
318 boolean csarAlreadyDeployed = false;
319 DistributionStatusEnum deployStatus = DistributionStatusEnum.DEPLOY_OK;
320 WatchdogComponentDistributionStatus wdStatus =
321 new WatchdogComponentDistributionStatus(iNotif.getDistributionID(), MSO);
323 csarAlreadyDeployed = toscaInstaller.isCsarAlreadyDeployed(toscaResourceStructure);
324 if (csarAlreadyDeployed) {
325 deployStatus = DistributionStatusEnum.ALREADY_DEPLOYED;
326 resourceStructure = new VfResourceStructure(iNotif, null);
327 errorMessage = String.format("Csar with UUID: %s already exists",
328 toscaResourceStructure.getToscaArtifact().getArtifactUUID());
329 wdStatus.setComponentDistributionStatus(DistributionStatusEnum.COMPONENT_DONE_OK.name());
330 watchdogCDStatusRepository.saveAndFlush(wdStatus);
331 logger.error(errorMessage);
333 } catch (ArtifactInstallerException e) {
334 deployStatus = DistributionStatusEnum.DEPLOY_ERROR;
335 resourceStructure = new VfResourceStructure(iNotif, null);
336 errorMessage = e.getMessage();
337 wdStatus.setComponentDistributionStatus(DistributionStatusEnum.COMPONENT_DONE_ERROR.name());
338 watchdogCDStatusRepository.saveAndFlush(wdStatus);
339 logger.warn("Tosca Checksums don't match, Tosca validation check failed", e);
342 if (deployStatus != DistributionStatusEnum.DEPLOY_OK) {
343 notifyErrorToAsdc(iNotif, toscaResourceStructure, deployStatus, resourceStructure, errorMessage);
346 return csarAlreadyDeployed;
349 protected IDistributionClientDownloadResult downloadTheArtifact(IArtifactInfo artifact, String distributionId)
350 throws ASDCDownloadException {
352 logger.info("Trying to download the artifact UUID: {} from URL: {}", artifact.getArtifactUUID(),
353 artifact.getArtifactURL());
354 IDistributionClientDownloadResult downloadResult;
357 downloadResult = distributionClient.download(artifact);
358 if (null == downloadResult) {
359 logger.info(LoggingAnchor.TWO, MessageEnum.ASDC_ARTIFACT_NULL.toString(), artifact.getArtifactUUID());
360 return downloadResult;
362 } catch (RuntimeException e) {
363 logger.debug("Not able to download the artifact due to an exception: " + artifact.getArtifactURL());
364 this.sendASDCNotification(NotificationType.DOWNLOAD, artifact.getArtifactURL(), asdcConfig.getConsumerID(),
365 distributionId, DistributionStatusEnum.DOWNLOAD_ERROR, e.getMessage(), System.currentTimeMillis());
367 throw new ASDCDownloadException("Exception caught when downloading the artifact", e);
370 if (DistributionActionResultEnum.SUCCESS.equals(downloadResult.getDistributionActionResult())) {
371 logger.info(LoggingAnchor.FOUR, MessageEnum.ASDC_ARTIFACT_DOWNLOAD_SUC.toString(),
372 artifact.getArtifactURL(), artifact.getArtifactUUID(), downloadResult.getArtifactPayload().length);
375 logger.error(LoggingAnchor.SEVEN, MessageEnum.ASDC_ARTIFACT_DOWNLOAD_FAIL.toString(),
376 artifact.getArtifactName(), artifact.getArtifactURL(), artifact.getArtifactUUID(),
377 downloadResult.getDistributionMessageResult(), ErrorCode.DataError.getValue(),
378 "ASDC artifact download fail");
380 this.sendASDCNotification(NotificationType.DOWNLOAD, artifact.getArtifactURL(), asdcConfig.getConsumerID(),
381 distributionId, DistributionStatusEnum.DOWNLOAD_ERROR,
382 downloadResult.getDistributionMessageResult(), System.currentTimeMillis());
384 throw new ASDCDownloadException("Artifact " + artifact.getArtifactName()
385 + " could not be downloaded from ASDC URL " + artifact.getArtifactURL() + UUID_PARAM
386 + artifact.getArtifactUUID() + ")" + System.lineSeparator() + "Error message is "
387 + downloadResult.getDistributionMessageResult() + System.lineSeparator());
391 this.sendASDCNotification(NotificationType.DOWNLOAD, artifact.getArtifactURL(), asdcConfig.getConsumerID(),
392 distributionId, DistributionStatusEnum.DOWNLOAD_OK, null, System.currentTimeMillis());
393 return downloadResult;
397 private void writeArtifactToFile(IArtifactInfo artifact, IDistributionClientDownloadResult resultArtifact) {
400 Paths.get(getMsoConfigPath(), "ASDC", artifact.getArtifactVersion(), artifact.getArtifactName())
401 .normalize().toString();
403 logger.info("Trying to write artifact UUID: {}, URL: {} to file: {}", artifact.getArtifactUUID(),
404 artifact.getArtifactURL(), filePath);
406 // make parent directory
407 File file = new File(filePath);
408 File fileParent = file.getParentFile();
409 if (!fileParent.exists()) {
413 byte[] payloadBytes = resultArtifact.getArtifactPayload();
415 try (FileOutputStream outFile = new FileOutputStream(filePath)) {
416 logger.info(LoggingAnchor.FOUR, MessageEnum.ASDC_RECEIVE_SERVICE_NOTIF.toString(),
417 "***WRITE FILE ARTIFACT NAME", "ASDC", artifact.getArtifactName());
418 outFile.write(payloadBytes, 0, payloadBytes.length);
419 } catch (Exception e) {
420 logger.debug("Exception :", e);
421 logger.error(LoggingAnchor.SEVEN, MessageEnum.ASDC_ARTIFACT_DOWNLOAD_FAIL.toString(),
422 artifact.getArtifactName(), artifact.getArtifactURL(), artifact.getArtifactUUID(),
423 resultArtifact.getDistributionMessageResult(), ErrorCode.DataError.getValue(),
424 "ASDC write to file failed");
430 protected void sendDeployNotificationsForResource(ResourceStructure resourceStructure,
431 DistributionStatusEnum distribStatus, String errorReason) {
433 for (IArtifactInfo artifactInfo : resourceStructure.getResourceInstance().getArtifacts()) {
435 if ((DistributionStatusEnum.DEPLOY_OK.equals(distribStatus)
436 && !("OTHER").equalsIgnoreCase(artifactInfo.getArtifactType())
437 && !resourceStructure.isAlreadyDeployed())
438 // This could be NULL if the artifact is a VF module artifact, this won't be present in the MAP
439 && resourceStructure.getArtifactsMapByUUID().get(artifactInfo.getArtifactUUID()) != null
440 && resourceStructure.getArtifactsMapByUUID().get(artifactInfo.getArtifactUUID())
441 .getDeployedInDb() == 0) {
442 this.sendASDCNotification(NotificationType.DEPLOY, artifactInfo.getArtifactURL(),
443 asdcConfig.getConsumerID(), resourceStructure.getNotification().getDistributionID(),
444 DistributionStatusEnum.DEPLOY_ERROR,
445 "The artifact has not been used by the modules defined in the resource",
446 System.currentTimeMillis());
448 this.sendASDCNotification(NotificationType.DEPLOY, artifactInfo.getArtifactURL(),
449 asdcConfig.getConsumerID(), resourceStructure.getNotification().getDistributionID(),
450 distribStatus, errorReason, System.currentTimeMillis());
455 protected void sendCsarDeployNotification(ResourceStructure resourceStructure,
456 ToscaResourceStructure toscaResourceStructure, DistributionStatusEnum statusEnum, String errorReason) {
458 IArtifactInfo csarArtifact = toscaResourceStructure.getToscaArtifact();
460 this.sendASDCNotification(NotificationType.DEPLOY, csarArtifact.getArtifactURL(), asdcConfig.getConsumerID(),
461 resourceStructure.getNotification().getDistributionID(), statusEnum, errorReason,
462 System.currentTimeMillis());
466 protected void deployResourceStructure(ResourceStructure resourceStructure,
467 ToscaResourceStructure toscaResourceStructure) throws ArtifactInstallerException {
469 logger.info(LoggingAnchor.FOUR, MessageEnum.ASDC_START_DEPLOY_ARTIFACT.toString(),
470 resourceStructure.getResourceInstance().getResourceInstanceName(),
471 resourceStructure.getResourceInstance().getResourceUUID(), "ASDC");
473 resourceStructure.prepareInstall();
474 toscaInstaller.installTheResource(toscaResourceStructure, resourceStructure);
476 } catch (ArtifactInstallerException e) {
477 logger.info(LoggingAnchor.SIX, MessageEnum.ASDC_ARTIFACT_DOWNLOAD_FAIL.toString(),
478 resourceStructure.getResourceInstance().getResourceName(),
479 resourceStructure.getResourceInstance().getResourceUUID(), resourceStructure.getNumberOfResources(),
480 "ASDC", "deployResourceStructure");
481 sendDeployNotificationsForResource(resourceStructure, DistributionStatusEnum.DEPLOY_ERROR, e.getMessage());
485 if (resourceStructure.isDeployedSuccessfully() || toscaResourceStructure.isDeployedSuccessfully()) {
486 logger.info(LoggingAnchor.SIX, MessageEnum.ASDC_ARTIFACT_DEPLOY_SUC.toString(),
487 resourceStructure.getResourceInstance().getResourceName(),
488 resourceStructure.getResourceInstance().getResourceUUID(), resourceStructure.getNumberOfResources(),
489 "ASDC", "deployResourceStructure");
490 sendDeployNotificationsForResource(resourceStructure, DistributionStatusEnum.DEPLOY_OK, null);
496 private enum NotificationType {
500 protected void sendASDCNotification(NotificationType notificationType, String artifactURL, String consumerID,
501 String distributionID, DistributionStatusEnum status, String errorReason, long timestamp) {
503 String event = "Sending " + notificationType.name() + "(" + status.name() + ")"
504 + " notification to ASDC for artifact:" + artifactURL;
506 if (errorReason != null) {
507 event = event + "(" + errorReason + ")";
509 logger.info(LoggingAnchor.SIX, MessageEnum.ASDC_SEND_NOTIF_ASDC.toString(), notificationType.name(),
510 status.name(), artifactURL, "ASDC", "sendASDCNotification");
515 IDistributionStatusMessage message =
516 new DistributionStatusMessage(artifactURL, consumerID, distributionID, status, timestamp);
517 if (errorReason != null) {
518 sendNotificationWithMessageAndErrorReason(notificationType, errorReason, message);
520 sendNotificationWithMessage(notificationType, message);
522 } catch (RuntimeException e) {
523 logger.warn(LoggingAnchor.FIVE, MessageEnum.ASDC_SEND_NOTIF_ASDC_EXEC.toString(), "ASDC",
524 "sendASDCNotification", ErrorCode.SchemaError.getValue(), "RuntimeException - sendASDCNotification",
529 private void sendNotificationWithMessage(NotificationType notificationType, IDistributionStatusMessage message) {
530 switch (notificationType) {
532 this.distributionClient.sendDownloadStatus(message);
535 this.distributionClient.sendDeploymentStatus(message);
542 private void sendNotificationWithMessageAndErrorReason(NotificationType notificationType, String errorReason,
543 IDistributionStatusMessage message) {
544 switch (notificationType) {
546 this.distributionClient.sendDownloadStatus(message, errorReason);
549 this.distributionClient.sendDeploymentStatus(message, errorReason);
556 protected void sendFinalDistributionStatus(String distributionID, DistributionStatusEnum status,
557 String errorReason) {
559 logger.debug("Enter sendFinalDistributionStatus with DistributionID " + distributionID + " and Status of "
560 + status.name() + " and ErrorReason " + errorReason);
562 long subStarttime = System.currentTimeMillis();
565 IFinalDistrStatusMessage finalDistribution = new FinalDistributionStatusMessage(distributionID, status,
566 subStarttime, asdcConfig.getConsumerID());
568 if (errorReason == null) {
569 this.distributionClient.sendFinalDistrStatus(finalDistribution);
571 this.distributionClient.sendFinalDistrStatus(finalDistribution, errorReason);
575 } catch (RuntimeException e) {
576 logger.debug("Exception caught in sendFinalDistributionStatus {}", e.getMessage());
577 logger.warn(LoggingAnchor.FIVE, MessageEnum.ASDC_SEND_NOTIF_ASDC_EXEC.toString(), "ASDC",
578 "sendASDCNotification", ErrorCode.SchemaError.getValue(), "RuntimeException - sendASDCNotification",
583 private Optional<String> getNotificationJson(INotificationData iNotif) {
584 ObjectMapper mapper = new ObjectMapper();
585 mapper.setSerializationInclusion(Include.NON_NULL);
586 mapper.setSerializationInclusion(Include.NON_EMPTY);
587 mapper.setSerializationInclusion(Include.NON_ABSENT);
588 mapper.enable(MapperFeature.USE_ANNOTATIONS);
589 mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
590 Optional<String> returnValue = Optional.empty();
592 returnValue = Optional.of(mapper.writeValueAsString(iNotif));
593 } catch (JsonProcessingException e) {
594 logger.error("Error converting incoming ASDC notification to JSON", e);
599 public void treatNotification(INotificationData iNotif) {
601 int noOfArtifacts = 0;
603 for (IResourceInstance resource : iNotif.getResources()) {
604 noOfArtifacts += resource.getArtifacts().size();
606 logger.info(LoggingAnchor.FOUR, MessageEnum.ASDC_RECEIVE_CALLBACK_NOTIF.toString(), noOfArtifacts,
607 iNotif.getServiceUUID(), "ASDC");
610 if (iNotif.getDistributionID() != null && !iNotif.getDistributionID().isEmpty()) {
611 MDC.put(ONAPLogConstants.MDCs.REQUEST_ID, iNotif.getDistributionID());
613 logger.debug(ASDCNotificationLogging.dumpASDCNotification(iNotif));
614 logger.info(LoggingAnchor.FOUR, MessageEnum.ASDC_RECEIVE_SERVICE_NOTIF.toString(), iNotif.getServiceUUID(),
615 "ASDC", "treatNotification");
617 this.changeControllerStatus(ASDCControllerStatus.BUSY);
618 Optional<String> notificationMessage = getNotificationJson(iNotif);
619 toscaInstaller.processWatchdog(iNotif.getDistributionID(), iNotif.getServiceUUID(), notificationMessage,
620 asdcConfig.getConsumerID());
622 // Process only the Resource artifacts in MSO
623 this.processResourceNotification(iNotif);
625 // ********************************************************************************************************
626 // Start Watchdog loop and wait for all components to complete before reporting final status back.
627 // **If timer expires first then we will report a Distribution Error back to ASDC
628 // ********************************************************************************************************
629 long initialStartTime = System.currentTimeMillis();
630 boolean componentsComplete = false;
631 String distributionStatus = null;
632 String watchdogError = null;
633 String overallStatus = null;
634 int watchDogTimeout = asdcConfig.getWatchDogTimeout() * 1000;
635 boolean isDeploySuccess = false;
637 while (!componentsComplete && (System.currentTimeMillis() - initialStartTime) < watchDogTimeout) {
640 distributionStatus = wd.getOverallDistributionStatus(iNotif.getDistributionID());
641 Thread.sleep(watchDogTimeout / 10);
642 } catch (Exception e) {
643 logger.debug("Exception in Watchdog Loop {}", e.getMessage());
644 Thread.sleep(watchDogTimeout / 10);
647 if (distributionStatus != null
648 && !distributionStatus.equalsIgnoreCase(DistributionStatus.INCOMPLETE.name())) {
650 if (distributionStatus.equalsIgnoreCase(DistributionStatus.SUCCESS.name())) {
651 isDeploySuccess = true;
652 overallStatus = DistributionStatusEnum.DISTRIBUTION_COMPLETE_OK.name();
654 overallStatus = DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name();
656 componentsComplete = true;
660 if (!componentsComplete) {
661 logger.debug("Timeout of {} seconds was reached before all components reported status",
663 watchdogError = "Timeout occurred while waiting for all components to report status";
664 overallStatus = DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name();
667 if (distributionStatus == null) {
668 overallStatus = DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name();
669 logger.debug("DistributionStatus is null for DistributionId: {}", iNotif.getDistributionID());
673 wd.executePatchAAI(iNotif.getDistributionID(), iNotif.getServiceInvariantUUID(), overallStatus);
674 logger.debug("A&AI Updated succefully with Distribution Status!");
675 } catch (Exception e) {
676 logger.debug("Exception in Watchdog executePatchAAI(): {}", e.getMessage());
677 watchdogError = "Error calling A&AI " + e.getMessage();
678 if (e.getCause() != null) {
679 logger.debug("Exception caused by: {}", e.getCause().getMessage());
683 wd.updateCatalogDBStatus(iNotif.getServiceInvariantUUID(), overallStatus);
685 if (isDeploySuccess && watchdogError == null) {
686 sendFinalDistributionStatus(iNotif.getDistributionID(), DistributionStatusEnum.DISTRIBUTION_COMPLETE_OK,
688 WatchdogDistributionStatus wds = new WatchdogDistributionStatus(iNotif.getDistributionID());
689 wds.setDistributionIdStatus(DistributionStatusEnum.DISTRIBUTION_COMPLETE_OK.toString());
692 sendFinalDistributionStatus(iNotif.getDistributionID(),
693 DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR, watchdogError);
694 WatchdogDistributionStatus wds = new WatchdogDistributionStatus(iNotif.getDistributionID());
695 wds.setDistributionIdStatus(DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.toString());
699 } catch (ObjectOptimisticLockingFailureException e) {
702 "OptimisticLockingFailure for DistributionId: {} Another process "
703 + "has already altered this distribution, so not going to process it on this site.",
704 iNotif.getDistributionID());
705 logger.error(LoggingAnchor.FIVE, MessageEnum.ASDC_GENERAL_EXCEPTION_ARG.toString(),
706 "Database concurrency exception: ", "ASDC", "treatNotification",
707 ErrorCode.BusinessProcessError.getValue(), "RuntimeException in treatNotification", e);
709 } catch (Exception e) {
710 logger.error("", MessageEnum.ASDC_GENERAL_EXCEPTION_ARG.toString(),
711 "Unexpected exception caught during the notification processing", "ASDC", "treatNotification",
712 ErrorCode.SchemaError.getValue(), "RuntimeException in treatNotification", e);
715 wd.executePatchAAI(iNotif.getDistributionID(), iNotif.getServiceInvariantUUID(),
716 DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name());
717 logger.debug("A&AI Updated succefully with Distribution Status of {}",
718 DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name());
719 } catch (Exception aaiException) {
720 logger.debug("Exception in executePatchAAI(): {}", aaiException);
721 if (aaiException.getCause() != null) {
722 logger.debug("Exception caused by: {}", aaiException.getCause().getMessage());
726 sendFinalDistributionStatus(iNotif.getDistributionID(), DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR,
729 WatchdogDistributionStatus wds = new WatchdogDistributionStatus(iNotif.getDistributionID());
730 wds.setDistributionIdStatus(DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.toString());
734 this.changeControllerStatus(ASDCControllerStatus.IDLE);
738 protected void processResourceNotification(INotificationData iNotif) {
739 // For each artifact, create a structure describing the VFModule in a ordered flat level
740 String msoConfigPath = getMsoConfigPath();
741 ToscaResourceStructure toscaResourceStructure = new ToscaResourceStructure(msoConfigPath);
742 DistributionStatusEnum deployStatus = DistributionStatusEnum.DEPLOY_OK;
743 String errorMessage = null;
744 boolean serviceDeployed = false;
747 this.processCsarServiceArtifacts(iNotif, toscaResourceStructure);
748 if (isCsarAlreadyDeployed(iNotif, toscaResourceStructure)) {
752 ResourceStructure resourceStructure = null;
753 for (IResourceInstance resource : iNotif.getResources()) {
755 String resourceType = resource.getResourceType();
756 boolean hasVFResource = false;
758 logger.info("Processing Resource Type: {}, Model UUID: {}", resourceType, resource.getResourceUUID());
760 resourceStructure = getResourceStructure(iNotif, resource, resourceType);
764 if (!this.checkResourceAlreadyDeployed(resourceStructure, serviceDeployed)) {
765 logger.debug("Processing Resource Type: " + resourceType + " and Model UUID: "
766 + resourceStructure.getResourceInstance().getResourceUUID());
769 if ("VF".equals(resourceType)) {
770 hasVFResource = true;
771 for (IArtifactInfo artifact : resource.getArtifacts()) {
772 IDistributionClientDownloadResult resultArtifact =
773 this.downloadTheArtifact(artifact, iNotif.getDistributionID());
774 if (resultArtifact == null) {
778 if (ASDCConfiguration.VF_MODULES_METADATA.equals(artifact.getArtifactType())) {
779 logger.debug("VF_MODULE_ARTIFACT: "
780 + new String(resultArtifact.getArtifactPayload(), StandardCharsets.UTF_8));
781 logger.debug(ASDCNotificationLogging
782 .dumpVfModuleMetaDataList(((VfResourceStructure) resourceStructure)
783 .decodeVfModuleArtifact(resultArtifact.getArtifactPayload())));
785 if (!ASDCConfiguration.WORKFLOW.equals(artifact.getArtifactType())) {
786 resourceStructure.addArtifactToStructure(distributionClient, artifact,
789 writeArtifactToFile(artifact, resultArtifact);
791 "Adding workflow artifact to structure: " + artifact.getArtifactName());
792 resourceStructure.addWorkflowArtifactToStructure(artifact, resultArtifact);
797 // Deploy VF resource and artifacts
798 logger.debug("Preparing to deploy Service: {}", iNotif.getServiceUUID());
801 this.deployResourceStructure(resourceStructure, toscaResourceStructure);
802 serviceDeployed = true;
806 } catch (ArtifactInstallerException e) {
807 deployStatus = DistributionStatusEnum.DEPLOY_ERROR;
808 errorMessage = e.getMessage();
809 logger.error("Exception occurred", e);
812 if (!hasVFResource) {
814 logger.debug("No resources found for Service: " + iNotif.getServiceUUID());
816 logger.debug("Preparing to deploy Service: {}", iNotif.getServiceUUID());
818 this.deployResourceStructure(resourceStructure, toscaResourceStructure);
819 serviceDeployed = true;
820 } catch (ArtifactInstallerException e) {
821 deployStatus = DistributionStatusEnum.DEPLOY_ERROR;
822 errorMessage = e.getMessage();
823 logger.error("Exception occurred", e);
828 this.sendCsarDeployNotification(resourceStructure, toscaResourceStructure, deployStatus, errorMessage);
830 } catch (ASDCDownloadException | UnsupportedEncodingException e) {
831 logger.error(LoggingAnchor.SIX, MessageEnum.ASDC_GENERAL_EXCEPTION_ARG.toString(),
832 "Exception caught during Installation of artifact", "ASDC", "processResourceNotification",
833 ErrorCode.BusinessProcessError.getValue(), "Exception in processResourceNotification", e);
837 private ResourceStructure getResourceStructure(INotificationData iNotif, IResourceInstance resource,
838 String resourceType) {
839 if ("VF".equals(resourceType)) {
840 return new VfResourceStructure(iNotif, resource);
842 if ("PNF".equals(resourceType)) {
843 return new PnfResourceStructure(iNotif, resource);
845 logger.info("No resources found for Service: {}", iNotif.getServiceUUID());
846 ResourceStructure resourceStructure = new VfResourceStructure(iNotif, new ResourceInstance());
847 resourceStructure.setResourceType(ResourceType.OTHER);
848 return resourceStructure;
851 private String getMsoConfigPath() {
852 String msoConfigPath = System.getProperty("mso.config.path");
853 if (msoConfigPath == null) {
854 logger.info("Unable to find the system property mso.config.path, use the default configuration");
855 msoConfigPath = asdcConfig.getPropertyOrNull("mso.config.defaultpath");
857 if (msoConfigPath == null) {
858 logger.info("Unable to find the property: {} from configuration.", "mso.config.defaultpath");
861 logger.info("MSO config path is: {}", msoConfigPath);
862 return msoConfigPath;
865 protected void processCsarServiceArtifacts(INotificationData iNotif,
866 ToscaResourceStructure toscaResourceStructure) {
868 List<IArtifactInfo> serviceArtifacts = iNotif.getServiceArtifacts();
870 for (IArtifactInfo artifact : serviceArtifacts) {
872 if (artifact.getArtifactType().equals(ASDCConfiguration.TOSCA_CSAR)) {
876 toscaResourceStructure.setToscaArtifact(artifact);
878 IDistributionClientDownloadResult resultArtifact =
879 this.downloadTheArtifact(artifact, iNotif.getDistributionID());
881 writeArtifactToFile(artifact, resultArtifact);
883 toscaResourceStructure.updateResourceStructure(artifact);
885 toscaResourceStructure.setServiceVersion(iNotif.getServiceVersion());
887 logger.debug(ASDCNotificationLogging.dumpCSARNotification(iNotif, toscaResourceStructure));
890 } catch (Exception e) {
891 logger.error(LoggingAnchor.SIX, MessageEnum.ASDC_GENERAL_EXCEPTION_ARG.toString(),
892 "Exception caught during processCsarServiceArtifacts", "ASDC",
893 "processCsarServiceArtifacts", ErrorCode.BusinessProcessError.getValue(),
894 "Exception in processCsarServiceArtifacts", e);
896 } else if (artifact.getArtifactType().equals(ASDCConfiguration.WORKFLOW)) {
900 IDistributionClientDownloadResult resultArtifact =
901 this.downloadTheArtifact(artifact, iNotif.getDistributionID());
903 writeArtifactToFile(artifact, resultArtifact);
905 toscaResourceStructure.setToscaArtifact(artifact);
907 logger.debug(ASDCNotificationLogging.dumpASDCNotification(iNotif));
910 } catch (Exception e) {
911 logger.info("Whats the error {}", e.getMessage());
912 logger.error(LoggingAnchor.SIX, MessageEnum.ASDC_GENERAL_EXCEPTION_ARG.toString(),
913 "Exception caught during processCsarServiceArtifacts", "ASDC",
914 "processCsarServiceArtifacts", ErrorCode.BusinessProcessError.getValue(),
915 "Exception in processCsarServiceArtifacts", e);
925 * @return the address of the ASDC we are connected to.
927 public String getAddress() {
928 if (asdcConfig != null) {
929 return asdcConfig.getAsdcAddress();
935 * @return the environment name of the ASDC we are connected to.
937 public String getEnvironment() {
938 if (asdcConfig != null) {
939 return asdcConfig.getEnvironmentName();