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.logging.filter.base.ErrorCode;
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.tosca.parser.impl.SdcPropertyNames;
54 import org.onap.sdc.toscaparser.api.elements.Metadata;
55 import org.onap.sdc.utils.DistributionActionResultEnum;
56 import org.onap.sdc.utils.DistributionStatusEnum;
57 import org.onap.so.asdc.activity.DeployActivitySpecs;
58 import org.onap.so.asdc.client.exceptions.ASDCControllerException;
59 import org.onap.so.asdc.client.exceptions.ASDCDownloadException;
60 import org.onap.so.asdc.client.exceptions.ASDCParametersException;
61 import org.onap.so.asdc.client.exceptions.ArtifactInstallerException;
62 import org.onap.so.asdc.installer.IVfResourceInstaller;
63 import org.onap.so.asdc.installer.PnfResourceStructure;
64 import org.onap.so.asdc.installer.ResourceStructure;
65 import org.onap.so.asdc.installer.ResourceType;
66 import org.onap.so.asdc.installer.ToscaResourceStructure;
67 import org.onap.so.asdc.installer.VfResourceStructure;
68 import org.onap.so.asdc.installer.heat.ToscaResourceInstaller;
69 import org.onap.so.asdc.tenantIsolation.DistributionStatus;
70 import org.onap.so.asdc.tenantIsolation.WatchdogDistribution;
71 import org.onap.so.asdc.util.ASDCNotificationLogging;
72 import org.onap.so.asdc.util.ZipParser;
73 import org.onap.so.db.request.beans.WatchdogComponentDistributionStatus;
74 import org.onap.so.db.request.beans.WatchdogDistributionStatus;
75 import org.onap.so.db.request.data.repository.WatchdogComponentDistributionStatusRepository;
76 import org.onap.so.db.request.data.repository.WatchdogDistributionStatusRepository;
77 import org.onap.so.logger.LoggingAnchor;
78 import org.onap.so.logger.MessageEnum;
79 import org.slf4j.Logger;
80 import org.slf4j.LoggerFactory;
82 import org.springframework.beans.factory.annotation.Autowired;
83 import org.springframework.orm.ObjectOptimisticLockingFailureException;
84 import org.springframework.stereotype.Component;
87 public class ASDCController {
89 protected static final Logger logger = LoggerFactory.getLogger(ASDCController.class);
91 private static final String UNKNOWN = "Unknown";
93 protected boolean isAsdcClientAutoManaged = false;
95 protected String controllerName;
97 private ASDCControllerStatus controllerStatus = ASDCControllerStatus.STOPPED;
99 protected int nbOfNotificationsOngoing = 0;
102 private ToscaResourceInstaller toscaInstaller;
105 private WatchdogDistributionStatusRepository wdsRepo;
108 protected WatchdogComponentDistributionStatusRepository watchdogCDStatusRepository;
111 private ASDCConfiguration asdcConfig;
114 private ASDCStatusCallBack asdcStatusCallBack;
117 private ASDCNotificationCallBack asdcNotificationCallBack;
119 private IDistributionClient distributionClient;
121 private static final String UUID_PARAM = "(UUID:";
123 protected static final String MSO = "SO";
126 private WatchdogDistribution wd;
129 DeployActivitySpecs deployActivitySpecs;
131 public ASDCController() {
135 public ASDCController(String controllerConfigName) {
136 isAsdcClientAutoManaged = true;
137 this.controllerName = controllerConfigName;
140 public ASDCController(String controllerConfigName, IDistributionClient asdcClient,
141 IVfResourceInstaller resourceinstaller) {
142 distributionClient = asdcClient;
145 public ASDCController(String controllerConfigName, IDistributionClient asdcClient) {
146 distributionClient = asdcClient;
147 this.controllerName = controllerConfigName;
150 public ASDCConfiguration getASDCConfiguration() {
154 public int getNbOfNotificationsOngoing() {
155 return nbOfNotificationsOngoing;
158 public IDistributionClient getDistributionClient() {
159 return distributionClient;
162 public void setDistributionClient(IDistributionClient distributionClient) {
163 this.distributionClient = distributionClient;
166 protected void changeControllerStatus(ASDCControllerStatus newControllerStatus) {
167 switch (newControllerStatus) {
170 ++this.nbOfNotificationsOngoing;
171 this.controllerStatus = newControllerStatus;
175 changeOnStatusIDLE(newControllerStatus);
179 this.controllerStatus = newControllerStatus;
185 private void changeOnStatusIDLE(ASDCControllerStatus newControllerStatus) {
186 if (this.nbOfNotificationsOngoing > 1) {
187 --this.nbOfNotificationsOngoing;
189 this.nbOfNotificationsOngoing = 0;
190 this.controllerStatus = newControllerStatus;
194 public ASDCControllerStatus getControllerStatus() {
195 return this.controllerStatus;
198 public String getControllerName() {
199 return controllerName;
202 public void setControllerName(String controllerName) {
203 this.controllerName = controllerName;
207 * This method initializes the ASDC Controller and the ASDC Client.
209 * @throws ASDCControllerException It throws an exception if the ASDC Client cannot be instantiated or if an init
210 * attempt is done when already initialized
211 * @throws ASDCParametersException If there is an issue with the parameters provided
212 * @throws IOException In case of issues when trying to load the key file
214 public void initASDC() throws ASDCControllerException {
215 logger.debug("Initialize the ASDC Controller");
217 throw new ASDCControllerException("The controller is already initialized, call the closeASDC method first");
220 if (asdcConfig != null) {
221 asdcConfig.setAsdcControllerName(controllerName);
224 if (this.distributionClient == null) {
225 distributionClient = DistributionClientFactory.createDistributionClient();
228 IDistributionClientResult result =
229 this.distributionClient.init(asdcConfig, asdcNotificationCallBack, asdcStatusCallBack);
230 if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
232 "ASDC distribution client init failed with reason:" + result.getDistributionMessageResult();
233 logger.debug(endEvent);
234 this.changeControllerStatus(ASDCControllerStatus.STOPPED);
235 throw new ASDCControllerException("Initialization of the ASDC Controller failed with reason: "
236 + result.getDistributionMessageResult());
239 result = this.distributionClient.start();
240 if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
242 "ASDC distribution client start failed with reason:" + result.getDistributionMessageResult();
243 logger.debug(endEvent);
244 this.changeControllerStatus(ASDCControllerStatus.STOPPED);
245 throw new ASDCControllerException(
246 "Startup of the ASDC Controller failed with reason: " + result.getDistributionMessageResult());
249 this.changeControllerStatus(ASDCControllerStatus.IDLE);
250 logger.info(LoggingAnchor.THREE, MessageEnum.ASDC_INIT_ASDC_CLIENT_SUC.toString(), "ASDC",
251 "changeControllerStatus");
255 * @return true if controller is stopped
257 public boolean isStopped() {
258 return this.getControllerStatus() == ASDCControllerStatus.STOPPED;
262 * This method closes the ASDC Controller and the ASDC Client.
264 * @throws ASDCControllerException It throws an exception if the ASDC Client cannot be closed because it's currently
265 * BUSY in processing notifications.
267 public void closeASDC() throws ASDCControllerException {
270 throw new ASDCControllerException("Cannot close the ASDC controller as it's currently in BUSY state");
272 if (this.distributionClient != null) {
273 this.distributionClient.stop();
274 // If auto managed we can set it to Null, ASDCController controls it.
275 // In the other case the client of this class has specified it, so we can't reset it
276 if (isAsdcClientAutoManaged) {
277 // Next init will initialize it with a new ASDC Client
278 this.distributionClient = null;
282 this.changeControllerStatus(ASDCControllerStatus.STOPPED);
286 * @return true if controller is currently processing notification
288 public boolean isBusy() {
289 return this.getControllerStatus() == ASDCControllerStatus.BUSY;
292 protected boolean checkResourceAlreadyDeployed(ResourceStructure resource, boolean serviceDeployed)
293 throws ArtifactInstallerException {
296 if (toscaInstaller.isResourceAlreadyDeployed(resource, serviceDeployed)) {
297 logger.info(LoggingAnchor.FOUR, MessageEnum.ASDC_ARTIFACT_ALREADY_EXIST.toString(),
298 resource.getResourceInstance().getResourceInstanceName(),
299 resource.getResourceInstance().getResourceUUID(), resource.getResourceInstance().getResourceName());
301 this.sendDeployNotificationsForResource(resource, DistributionStatusEnum.ALREADY_DOWNLOADED, null);
302 this.sendDeployNotificationsForResource(resource, DistributionStatusEnum.ALREADY_DEPLOYED, null);
310 protected void notifyErrorToAsdc(INotificationData iNotif, ToscaResourceStructure toscaResourceStructure,
311 DistributionStatusEnum deployStatus, VfResourceStructure resourceStructure, String errorMessage) {
312 // do csar lever first
313 this.sendCsarDeployNotification(resourceStructure, toscaResourceStructure, deployStatus, errorMessage);
315 for (IResourceInstance resource : iNotif.getResources()) {
316 resourceStructure = new VfResourceStructure(iNotif, resource);
317 errorMessage = String.format("Resource with UUID: %s already exists", resource.getResourceUUID());
318 this.sendCsarDeployNotification(resourceStructure, toscaResourceStructure, deployStatus, errorMessage);
322 protected boolean isCsarAlreadyDeployed(INotificationData iNotif, ToscaResourceStructure toscaResourceStructure) {
323 VfResourceStructure resourceStructure = null;
324 String errorMessage = "";
325 boolean csarAlreadyDeployed = false;
326 DistributionStatusEnum deployStatus = DistributionStatusEnum.DEPLOY_OK;
327 WatchdogComponentDistributionStatus wdStatus =
328 new WatchdogComponentDistributionStatus(iNotif.getDistributionID(), MSO);
330 csarAlreadyDeployed = toscaInstaller.isCsarAlreadyDeployed(toscaResourceStructure);
331 if (csarAlreadyDeployed) {
332 deployStatus = DistributionStatusEnum.ALREADY_DEPLOYED;
333 resourceStructure = new VfResourceStructure(iNotif, null);
334 errorMessage = String.format("Csar with UUID: %s already exists",
335 toscaResourceStructure.getToscaArtifact().getArtifactUUID());
336 wdStatus.setComponentDistributionStatus(DistributionStatusEnum.COMPONENT_DONE_OK.name());
337 watchdogCDStatusRepository.saveAndFlush(wdStatus);
338 logger.error(errorMessage);
340 } catch (ArtifactInstallerException e) {
341 deployStatus = DistributionStatusEnum.DEPLOY_ERROR;
342 resourceStructure = new VfResourceStructure(iNotif, null);
343 errorMessage = e.getMessage();
344 wdStatus.setComponentDistributionStatus(DistributionStatusEnum.COMPONENT_DONE_ERROR.name());
345 watchdogCDStatusRepository.saveAndFlush(wdStatus);
346 logger.warn("Tosca Checksums don't match, Tosca validation check failed", e);
349 if (deployStatus != DistributionStatusEnum.DEPLOY_OK) {
350 notifyErrorToAsdc(iNotif, toscaResourceStructure, deployStatus, resourceStructure, errorMessage);
353 return csarAlreadyDeployed;
356 protected IDistributionClientDownloadResult downloadTheArtifact(IArtifactInfo artifact, String distributionId)
357 throws ASDCDownloadException {
359 logger.info("Trying to download the artifact UUID: {} from URL: {}", artifact.getArtifactUUID(),
360 artifact.getArtifactURL());
361 IDistributionClientDownloadResult downloadResult;
364 downloadResult = distributionClient.download(artifact);
365 if (null == downloadResult) {
366 logger.info(LoggingAnchor.TWO, MessageEnum.ASDC_ARTIFACT_NULL.toString(), artifact.getArtifactUUID());
367 return downloadResult;
369 } catch (RuntimeException e) {
370 logger.debug("Not able to download the artifact due to an exception: " + artifact.getArtifactURL());
371 this.sendASDCNotification(NotificationType.DOWNLOAD, artifact.getArtifactURL(), asdcConfig.getConsumerID(),
372 distributionId, DistributionStatusEnum.DOWNLOAD_ERROR, e.getMessage(), System.currentTimeMillis());
374 throw new ASDCDownloadException("Exception caught when downloading the artifact", e);
377 if (DistributionActionResultEnum.SUCCESS.equals(downloadResult.getDistributionActionResult())) {
378 logger.info(LoggingAnchor.FOUR, MessageEnum.ASDC_ARTIFACT_DOWNLOAD_SUC.toString(),
379 artifact.getArtifactURL(), artifact.getArtifactUUID(), downloadResult.getArtifactPayload().length);
382 logger.error(LoggingAnchor.SEVEN, MessageEnum.ASDC_ARTIFACT_DOWNLOAD_FAIL.toString(),
383 artifact.getArtifactName(), artifact.getArtifactURL(), artifact.getArtifactUUID(),
384 downloadResult.getDistributionMessageResult(), ErrorCode.DataError.getValue(),
385 "ASDC artifact download fail");
387 this.sendASDCNotification(NotificationType.DOWNLOAD, artifact.getArtifactURL(), asdcConfig.getConsumerID(),
388 distributionId, DistributionStatusEnum.DOWNLOAD_ERROR,
389 downloadResult.getDistributionMessageResult(), System.currentTimeMillis());
391 throw new ASDCDownloadException("Artifact " + artifact.getArtifactName()
392 + " could not be downloaded from ASDC URL " + artifact.getArtifactURL() + UUID_PARAM
393 + artifact.getArtifactUUID() + ")" + System.lineSeparator() + "Error message is "
394 + downloadResult.getDistributionMessageResult() + System.lineSeparator());
398 this.sendASDCNotification(NotificationType.DOWNLOAD, artifact.getArtifactURL(), asdcConfig.getConsumerID(),
399 distributionId, DistributionStatusEnum.DOWNLOAD_OK, null, System.currentTimeMillis());
400 return downloadResult;
404 private void writeArtifactToFile(IArtifactInfo artifact, IDistributionClientDownloadResult resultArtifact) {
407 Paths.get(getMsoConfigPath(), "ASDC", artifact.getArtifactVersion(), artifact.getArtifactName())
408 .normalize().toString();
410 logger.info("Trying to write artifact UUID: {}, URL: {} to file: {}", artifact.getArtifactUUID(),
411 artifact.getArtifactURL(), filePath);
413 // make parent directory
414 File file = new File(filePath);
415 File fileParent = file.getParentFile();
416 if (!fileParent.exists()) {
420 byte[] payloadBytes = resultArtifact.getArtifactPayload();
422 try (FileOutputStream outFile = new FileOutputStream(filePath)) {
423 logger.info(LoggingAnchor.FOUR, MessageEnum.ASDC_RECEIVE_SERVICE_NOTIF.toString(),
424 "***WRITE FILE ARTIFACT NAME", "ASDC", artifact.getArtifactName());
425 outFile.write(payloadBytes, 0, payloadBytes.length);
426 } catch (Exception e) {
427 logger.debug("Exception :", e);
428 logger.error(LoggingAnchor.SEVEN, MessageEnum.ASDC_ARTIFACT_DOWNLOAD_FAIL.toString(),
429 artifact.getArtifactName(), artifact.getArtifactURL(), artifact.getArtifactUUID(),
430 resultArtifact.getDistributionMessageResult(), ErrorCode.DataError.getValue(),
431 "ASDC write to file failed");
437 protected void sendDeployNotificationsForResource(ResourceStructure resourceStructure,
438 DistributionStatusEnum distribStatus, String errorReason) {
440 for (IArtifactInfo artifactInfo : resourceStructure.getResourceInstance().getArtifacts()) {
442 if ((DistributionStatusEnum.DEPLOY_OK.equals(distribStatus)
443 && !("OTHER").equalsIgnoreCase(artifactInfo.getArtifactType())
444 && !resourceStructure.isAlreadyDeployed())
445 // This could be NULL if the artifact is a VF module artifact, this won't be present in the MAP
446 && resourceStructure.getArtifactsMapByUUID().get(artifactInfo.getArtifactUUID()) != null
447 && resourceStructure.getArtifactsMapByUUID().get(artifactInfo.getArtifactUUID())
448 .getDeployedInDb() == 0) {
449 this.sendASDCNotification(NotificationType.DEPLOY, artifactInfo.getArtifactURL(),
450 asdcConfig.getConsumerID(), resourceStructure.getNotification().getDistributionID(),
451 DistributionStatusEnum.DEPLOY_ERROR,
452 "The artifact has not been used by the modules defined in the resource",
453 System.currentTimeMillis());
455 this.sendASDCNotification(NotificationType.DEPLOY, artifactInfo.getArtifactURL(),
456 asdcConfig.getConsumerID(), resourceStructure.getNotification().getDistributionID(),
457 distribStatus, errorReason, System.currentTimeMillis());
462 protected void sendCsarDeployNotification(ResourceStructure resourceStructure,
463 ToscaResourceStructure toscaResourceStructure, DistributionStatusEnum statusEnum, String errorReason) {
465 IArtifactInfo csarArtifact = toscaResourceStructure.getToscaArtifact();
467 this.sendASDCNotification(NotificationType.DEPLOY, csarArtifact.getArtifactURL(), asdcConfig.getConsumerID(),
468 resourceStructure.getNotification().getDistributionID(), statusEnum, errorReason,
469 System.currentTimeMillis());
473 protected void deployResourceStructure(ResourceStructure resourceStructure,
474 ToscaResourceStructure toscaResourceStructure) throws ArtifactInstallerException {
476 logger.info(LoggingAnchor.FOUR, MessageEnum.ASDC_START_DEPLOY_ARTIFACT.toString(),
477 resourceStructure.getResourceInstance().getResourceInstanceName(),
478 resourceStructure.getResourceInstance().getResourceUUID(), "ASDC");
480 resourceStructure.prepareInstall();
481 toscaInstaller.installTheResource(toscaResourceStructure, resourceStructure);
483 } catch (ArtifactInstallerException e) {
484 logger.info(LoggingAnchor.SIX, MessageEnum.ASDC_ARTIFACT_DOWNLOAD_FAIL.toString(),
485 resourceStructure.getResourceInstance().getResourceName(),
486 resourceStructure.getResourceInstance().getResourceUUID(), resourceStructure.getNumberOfResources(),
487 "ASDC", "deployResourceStructure");
488 sendDeployNotificationsForResource(resourceStructure, DistributionStatusEnum.DEPLOY_ERROR, e.getMessage());
492 if (resourceStructure.isDeployedSuccessfully() || toscaResourceStructure.isDeployedSuccessfully()) {
493 logger.info(LoggingAnchor.SIX, MessageEnum.ASDC_ARTIFACT_DEPLOY_SUC.toString(),
494 resourceStructure.getResourceInstance().getResourceName(),
495 resourceStructure.getResourceInstance().getResourceUUID(), resourceStructure.getNumberOfResources(),
496 "ASDC", "deployResourceStructure");
497 sendDeployNotificationsForResource(resourceStructure, DistributionStatusEnum.DEPLOY_OK, null);
503 private enum NotificationType {
507 protected void sendASDCNotification(NotificationType notificationType, String artifactURL, String consumerID,
508 String distributionID, DistributionStatusEnum status, String errorReason, long timestamp) {
510 String event = "Sending " + notificationType.name() + "(" + status.name() + ")"
511 + " notification to ASDC for artifact:" + artifactURL;
513 if (errorReason != null) {
514 event = event + "(" + errorReason + ")";
516 logger.info(LoggingAnchor.SIX, MessageEnum.ASDC_SEND_NOTIF_ASDC.toString(), notificationType.name(),
517 status.name(), artifactURL, "ASDC", "sendASDCNotification");
522 IDistributionStatusMessage message =
523 new DistributionStatusMessage(artifactURL, consumerID, distributionID, status, timestamp);
524 if (errorReason != null) {
525 sendNotificationWithMessageAndErrorReason(notificationType, errorReason, message);
527 sendNotificationWithMessage(notificationType, message);
529 } catch (RuntimeException e) {
530 logger.warn(LoggingAnchor.FIVE, MessageEnum.ASDC_SEND_NOTIF_ASDC_EXEC.toString(), "ASDC",
531 "sendASDCNotification", ErrorCode.SchemaError.getValue(), "RuntimeException - sendASDCNotification",
536 private void sendNotificationWithMessage(NotificationType notificationType, IDistributionStatusMessage message) {
537 switch (notificationType) {
539 this.distributionClient.sendDownloadStatus(message);
542 this.distributionClient.sendDeploymentStatus(message);
549 private void sendNotificationWithMessageAndErrorReason(NotificationType notificationType, String errorReason,
550 IDistributionStatusMessage message) {
551 switch (notificationType) {
553 this.distributionClient.sendDownloadStatus(message, errorReason);
556 this.distributionClient.sendDeploymentStatus(message, errorReason);
563 protected void sendFinalDistributionStatus(String distributionID, DistributionStatusEnum status,
564 String errorReason) {
566 logger.debug("Enter sendFinalDistributionStatus with DistributionID " + distributionID + " and Status of "
567 + status.name() + " and ErrorReason " + errorReason);
569 long subStarttime = System.currentTimeMillis();
572 IFinalDistrStatusMessage finalDistribution = new FinalDistributionStatusMessage(distributionID, status,
573 subStarttime, asdcConfig.getConsumerID());
575 if (errorReason == null) {
576 this.distributionClient.sendFinalDistrStatus(finalDistribution);
578 this.distributionClient.sendFinalDistrStatus(finalDistribution, errorReason);
582 } catch (RuntimeException e) {
583 logger.debug("Exception caught in sendFinalDistributionStatus {}", e.getMessage());
584 logger.warn(LoggingAnchor.FIVE, MessageEnum.ASDC_SEND_NOTIF_ASDC_EXEC.toString(), "ASDC",
585 "sendASDCNotification", ErrorCode.SchemaError.getValue(), "RuntimeException - sendASDCNotification",
590 private Optional<String> getNotificationJson(INotificationData iNotif) {
591 ObjectMapper mapper = new ObjectMapper();
592 mapper.setSerializationInclusion(Include.NON_NULL);
593 mapper.setSerializationInclusion(Include.NON_EMPTY);
594 mapper.setSerializationInclusion(Include.NON_ABSENT);
595 mapper.enable(MapperFeature.USE_ANNOTATIONS);
596 mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
597 Optional<String> returnValue = Optional.empty();
599 returnValue = Optional.of(mapper.writeValueAsString(iNotif));
600 } catch (JsonProcessingException e) {
601 logger.error("Error converting incoming ASDC notification to JSON", e);
606 public void treatNotification(INotificationData iNotif) {
608 int noOfArtifacts = 0;
610 for (IResourceInstance resource : iNotif.getResources()) {
611 noOfArtifacts += resource.getArtifacts().size();
613 logger.info(LoggingAnchor.FOUR, MessageEnum.ASDC_RECEIVE_CALLBACK_NOTIF.toString(), noOfArtifacts,
614 iNotif.getServiceUUID(), "ASDC");
617 if (iNotif.getDistributionID() != null && !iNotif.getDistributionID().isEmpty()) {
618 MDC.put(ONAPLogConstants.MDCs.REQUEST_ID, iNotif.getDistributionID());
620 logger.debug(ASDCNotificationLogging.dumpASDCNotification(iNotif));
621 logger.info(LoggingAnchor.FOUR, MessageEnum.ASDC_RECEIVE_SERVICE_NOTIF.toString(), iNotif.getServiceUUID(),
622 "ASDC", "treatNotification");
624 this.changeControllerStatus(ASDCControllerStatus.BUSY);
625 Optional<String> notificationMessage = getNotificationJson(iNotif);
626 toscaInstaller.processWatchdog(iNotif.getDistributionID(), iNotif.getServiceUUID(), notificationMessage,
627 asdcConfig.getConsumerID());
629 // Process only the Resource artifacts in MSO
630 this.processResourceNotification(iNotif);
632 // ********************************************************************************************************
633 // Start Watchdog loop and wait for all components to complete before reporting final status back.
634 // **If timer expires first then we will report a Distribution Error back to ASDC
635 // ********************************************************************************************************
636 long initialStartTime = System.currentTimeMillis();
637 boolean componentsComplete = false;
638 String distributionStatus = null;
639 String watchdogError = null;
640 String overallStatus = null;
641 int watchDogTimeout = asdcConfig.getWatchDogTimeout() * 1000;
642 boolean isDeploySuccess = false;
644 while (!componentsComplete && (System.currentTimeMillis() - initialStartTime) < watchDogTimeout) {
647 distributionStatus = wd.getOverallDistributionStatus(iNotif.getDistributionID());
648 Thread.sleep(watchDogTimeout / 10);
649 } catch (Exception e) {
650 logger.debug("Exception in Watchdog Loop {}", e.getMessage());
651 Thread.sleep(watchDogTimeout / 10);
654 if (distributionStatus != null
655 && !distributionStatus.equalsIgnoreCase(DistributionStatus.INCOMPLETE.name())) {
657 if (distributionStatus.equalsIgnoreCase(DistributionStatus.SUCCESS.name())) {
658 isDeploySuccess = true;
659 overallStatus = DistributionStatusEnum.DISTRIBUTION_COMPLETE_OK.name();
661 overallStatus = DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name();
663 componentsComplete = true;
667 if (!componentsComplete) {
668 logger.debug("Timeout of {} seconds was reached before all components reported status",
670 watchdogError = "Timeout occurred while waiting for all components to report status";
671 overallStatus = DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name();
674 if (distributionStatus == null) {
675 overallStatus = DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name();
676 logger.debug("DistributionStatus is null for DistributionId: {}", iNotif.getDistributionID());
680 wd.executePatchAAI(iNotif.getDistributionID(), iNotif.getServiceInvariantUUID(), overallStatus);
681 logger.debug("A&AI Updated succefully with Distribution Status!");
682 } catch (Exception e) {
683 logger.debug("Exception in Watchdog executePatchAAI(): {}", e.getMessage());
684 watchdogError = "Error calling A&AI " + e.getMessage();
685 if (e.getCause() != null) {
686 logger.debug("Exception caused by: {}", e.getCause().getMessage());
690 wd.updateCatalogDBStatus(iNotif.getServiceInvariantUUID(), overallStatus);
692 if (isDeploySuccess && watchdogError == null) {
693 sendFinalDistributionStatus(iNotif.getDistributionID(), DistributionStatusEnum.DISTRIBUTION_COMPLETE_OK,
695 WatchdogDistributionStatus wds = new WatchdogDistributionStatus(iNotif.getDistributionID());
696 wds.setDistributionIdStatus(DistributionStatusEnum.DISTRIBUTION_COMPLETE_OK.toString());
699 sendFinalDistributionStatus(iNotif.getDistributionID(),
700 DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR, watchdogError);
701 WatchdogDistributionStatus wds = new WatchdogDistributionStatus(iNotif.getDistributionID());
702 wds.setDistributionIdStatus(DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.toString());
706 } catch (ObjectOptimisticLockingFailureException e) {
709 "OptimisticLockingFailure for DistributionId: {} Another process "
710 + "has already altered this distribution, so not going to process it on this site.",
711 iNotif.getDistributionID());
712 logger.error(LoggingAnchor.FIVE, MessageEnum.ASDC_GENERAL_EXCEPTION_ARG.toString(),
713 "Database concurrency exception: ", "ASDC", "treatNotification",
714 ErrorCode.BusinessProcessError.getValue(), "RuntimeException in treatNotification", e);
716 } catch (Exception e) {
717 logger.error("", MessageEnum.ASDC_GENERAL_EXCEPTION_ARG.toString(),
718 "Unexpected exception caught during the notification processing", "ASDC", "treatNotification",
719 ErrorCode.SchemaError.getValue(), "RuntimeException in treatNotification", e);
722 wd.executePatchAAI(iNotif.getDistributionID(), iNotif.getServiceInvariantUUID(),
723 DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name());
724 logger.debug("A&AI Updated succefully with Distribution Status of {}",
725 DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name());
726 } catch (Exception aaiException) {
727 logger.debug("Exception in executePatchAAI(): {}", aaiException);
728 if (aaiException.getCause() != null) {
729 logger.debug("Exception caused by: {}", aaiException.getCause().getMessage());
733 sendFinalDistributionStatus(iNotif.getDistributionID(), DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR,
736 WatchdogDistributionStatus wds = new WatchdogDistributionStatus(iNotif.getDistributionID());
737 wds.setDistributionIdStatus(DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.toString());
741 this.changeControllerStatus(ASDCControllerStatus.IDLE);
745 protected void processResourceNotification(INotificationData iNotif) {
746 // For each artifact, create a structure describing the VFModule in a ordered flat level
747 ResourceStructure resourceStructure = null;
748 String msoConfigPath = getMsoConfigPath();
749 ToscaResourceStructure toscaResourceStructure = new ToscaResourceStructure(msoConfigPath);
750 DistributionStatusEnum deployStatus = DistributionStatusEnum.DEPLOY_OK;
751 String errorMessage = null;
752 boolean serviceDeployed = false;
755 this.processCsarServiceArtifacts(iNotif, toscaResourceStructure);
756 if (isCsarAlreadyDeployed(iNotif, toscaResourceStructure)) {
759 // process NsstResource
760 this.processNsstNotification(iNotif, toscaResourceStructure);
762 if (iNotif.getResources().isEmpty()) {
763 logger.error("Service Model contains no resources.");
767 for (IResourceInstance resource : iNotif.getResources()) {
769 String resourceType = resource.getResourceType();
770 boolean hasVFResource = false;
772 logger.info("Processing Resource Type: {}, Model UUID: {}", resourceType, resource.getResourceUUID());
774 resourceStructure = getResourceStructure(iNotif, resource, resourceType);
778 if (!this.checkResourceAlreadyDeployed(resourceStructure, serviceDeployed)) {
779 logger.debug("Processing Resource Type: " + resourceType + " and Model UUID: "
780 + resourceStructure.getResourceInstance().getResourceUUID());
783 if ("VF".equals(resourceType)) {
784 hasVFResource = true;
785 for (IArtifactInfo artifact : resource.getArtifacts()) {
786 IDistributionClientDownloadResult resultArtifact =
787 this.downloadTheArtifact(artifact, iNotif.getDistributionID());
788 if (resultArtifact == null) {
792 if (ASDCConfiguration.VF_MODULES_METADATA.equals(artifact.getArtifactType())) {
793 logger.debug("VF_MODULE_ARTIFACT: "
794 + new String(resultArtifact.getArtifactPayload(), StandardCharsets.UTF_8));
795 logger.debug(ASDCNotificationLogging
796 .dumpVfModuleMetaDataList(((VfResourceStructure) resourceStructure)
797 .decodeVfModuleArtifact(resultArtifact.getArtifactPayload())));
799 if (!ASDCConfiguration.WORKFLOW.equals(artifact.getArtifactType())) {
800 resourceStructure.addArtifactToStructure(distributionClient, artifact,
803 writeArtifactToFile(artifact, resultArtifact);
805 "Adding workflow artifact to structure: " + artifact.getArtifactName());
806 resourceStructure.addWorkflowArtifactToStructure(artifact, resultArtifact);
811 // Deploy VF resource and artifacts
812 logger.debug("Preparing to deploy Service: {}", iNotif.getServiceUUID());
815 this.deployResourceStructure(resourceStructure, toscaResourceStructure);
816 serviceDeployed = true;
820 } catch (ArtifactInstallerException e) {
821 deployStatus = DistributionStatusEnum.DEPLOY_ERROR;
822 errorMessage = e.getMessage();
823 logger.error("Exception occurred", e);
826 if (!hasVFResource) {
828 logger.debug("No resources found for Service: " + iNotif.getServiceUUID());
830 logger.debug("Preparing to deploy Service: {}", iNotif.getServiceUUID());
832 this.deployResourceStructure(resourceStructure, toscaResourceStructure);
833 serviceDeployed = true;
834 } catch (ArtifactInstallerException e) {
835 deployStatus = DistributionStatusEnum.DEPLOY_ERROR;
836 errorMessage = e.getMessage();
837 logger.error("Exception occurred", e);
842 this.sendCsarDeployNotification(resourceStructure, toscaResourceStructure, deployStatus, errorMessage);
844 } catch (ASDCDownloadException | UnsupportedEncodingException e) {
845 logger.error(LoggingAnchor.SIX, MessageEnum.ASDC_GENERAL_EXCEPTION_ARG.toString(),
846 "Exception caught during Installation of artifact", "ASDC", "processResourceNotification",
847 ErrorCode.BusinessProcessError.getValue(), "Exception in processResourceNotification", e);
851 private ResourceStructure getResourceStructure(INotificationData iNotif, IResourceInstance resource,
852 String resourceType) {
853 if ("VF".equals(resourceType)) {
854 return new VfResourceStructure(iNotif, resource);
856 if ("PNF".equals(resourceType)) {
857 return new PnfResourceStructure(iNotif, resource);
859 logger.info("No resources found for Service: {}", iNotif.getServiceUUID());
860 ResourceStructure resourceStructure = new VfResourceStructure(iNotif, new ResourceInstance());
861 resourceStructure.setResourceType(ResourceType.OTHER);
862 return resourceStructure;
865 private String getMsoConfigPath() {
866 String msoConfigPath = System.getProperty("mso.config.path");
867 if (msoConfigPath == null) {
868 logger.info("Unable to find the system property mso.config.path, use the default configuration");
869 msoConfigPath = asdcConfig.getPropertyOrNull("mso.config.defaultpath");
871 if (msoConfigPath == null) {
872 logger.info("Unable to find the property: {} from configuration.", "mso.config.defaultpath");
875 logger.info("MSO config path is: {}", msoConfigPath);
876 return msoConfigPath;
879 protected void processCsarServiceArtifacts(INotificationData iNotif,
880 ToscaResourceStructure toscaResourceStructure) {
882 List<IArtifactInfo> serviceArtifacts = iNotif.getServiceArtifacts();
884 for (IArtifactInfo artifact : serviceArtifacts) {
886 if (artifact.getArtifactType().equals(ASDCConfiguration.TOSCA_CSAR)) {
890 toscaResourceStructure.setToscaArtifact(artifact);
892 IDistributionClientDownloadResult resultArtifact =
893 this.downloadTheArtifact(artifact, iNotif.getDistributionID());
895 writeArtifactToFile(artifact, resultArtifact);
897 toscaResourceStructure.updateResourceStructure(artifact);
899 toscaResourceStructure.setServiceVersion(iNotif.getServiceVersion());
901 logger.debug(ASDCNotificationLogging.dumpCSARNotification(iNotif, toscaResourceStructure));
904 } catch (Exception e) {
905 logger.error(LoggingAnchor.SIX, MessageEnum.ASDC_GENERAL_EXCEPTION_ARG.toString(),
906 "Exception caught during processCsarServiceArtifacts", "ASDC",
907 "processCsarServiceArtifacts", ErrorCode.BusinessProcessError.getValue(),
908 "Exception in processCsarServiceArtifacts", e);
910 } else if (artifact.getArtifactType().equals(ASDCConfiguration.WORKFLOW)) {
914 IDistributionClientDownloadResult resultArtifact =
915 this.downloadTheArtifact(artifact, iNotif.getDistributionID());
917 writeArtifactToFile(artifact, resultArtifact);
919 toscaResourceStructure.setToscaArtifact(artifact);
921 logger.debug(ASDCNotificationLogging.dumpASDCNotification(iNotif));
924 } catch (Exception e) {
925 logger.info("Whats the error {}", e.getMessage());
926 logger.error(LoggingAnchor.SIX, MessageEnum.ASDC_GENERAL_EXCEPTION_ARG.toString(),
927 "Exception caught during processCsarServiceArtifacts", "ASDC",
928 "processCsarServiceArtifacts", ErrorCode.BusinessProcessError.getValue(),
929 "Exception in processCsarServiceArtifacts", e);
931 } else if (artifact.getArtifactType().equals(ASDCConfiguration.OTHER)) {
933 IDistributionClientDownloadResult resultArtifact =
934 this.downloadTheArtifact(artifact, iNotif.getDistributionID());
936 writeArtifactToFile(artifact, resultArtifact);
938 toscaResourceStructure.setToscaArtifact(artifact);
940 toscaResourceStructure.setServiceVersion(iNotif.getServiceVersion());
942 } catch (ASDCDownloadException e) {
943 logger.error(LoggingAnchor.SIX, MessageEnum.ASDC_GENERAL_EXCEPTION_ARG.toString(),
944 "Exception caught during processCsarServiceArtifacts", "ASDC",
945 "processCsarServiceArtifacts", ErrorCode.BusinessProcessError.getValue(),
946 "Exception in processCsarServiceArtifacts", e);
956 * @return the address of the ASDC we are connected to.
958 public String getAddress() {
959 if (asdcConfig != null) {
960 return asdcConfig.getAsdcAddress();
966 * @return the environment name of the ASDC we are connected to.
968 public String getEnvironment() {
969 if (asdcConfig != null) {
970 return asdcConfig.getEnvironmentName();
975 private void processNsstNotification(INotificationData iNotif, ToscaResourceStructure toscaResourceStructure) {
976 Metadata serviceMetadata = toscaResourceStructure.getServiceMetadata();
978 String category = serviceMetadata.getValue(SdcPropertyNames.PROPERTY_NAME_CATEGORY);
979 boolean isNeedInital = (category.contains("NSST") || category.equalsIgnoreCase("TN Network Requirement"))
980 && iNotif.getResources().isEmpty();
982 String artifactContent = null;
983 List<IArtifactInfo> serviceArtifacts = iNotif.getServiceArtifacts();
984 Optional<IArtifactInfo> artifactOpt = serviceArtifacts.stream()
985 .filter(e -> e.getArtifactType().equalsIgnoreCase("WORKFLOW")).findFirst();
986 if (artifactOpt.isPresent()) {
987 IArtifactInfo artifactInfo = artifactOpt.get();
988 logger.debug("Ready to parse this serviceArtifactUUID: " + artifactInfo.getArtifactUUID());
989 String filePath = Paths.get(getMsoConfigPath(), "ASDC", artifactInfo.getArtifactVersion(),
990 artifactInfo.getArtifactName()).normalize().toString();
991 ZipParser zipParserInstance = ZipParser.getInstance();
992 artifactContent = zipParserInstance.parseJsonForZip(filePath);
994 "serviceArtifact parsing success! serviceArtifactUUID: " + artifactInfo.getArtifactUUID());
996 ResourceStructure resourceStructure = new VfResourceStructure(iNotif, new ResourceInstance());
997 resourceStructure.setResourceType(ResourceType.OTHER);
998 toscaInstaller.installNsstService(toscaResourceStructure, (VfResourceStructure) resourceStructure,
1001 logger.debug("serviceArtifact is null");
1002 toscaInstaller.installNsstService(toscaResourceStructure, null, null);
1007 } catch (IOException e) {
1008 logger.error("serviceArtifact parse failure for service uuid: "
1009 + serviceMetadata.getValue(SdcPropertyNames.PROPERTY_NAME_CATEGORY));
1010 } catch (Exception e) {
1011 logger.error("error NSST process resource failure ", e);