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.sdc.tosca.parser.impl.SdcPropertyNames;
43 import org.onap.sdc.toscaparser.api.elements.Metadata;
44 import org.onap.so.asdc.util.ZipParser;
45 import org.onap.so.logger.LoggingAnchor;
46 import org.onap.logging.ref.slf4j.ONAPLogConstants;
47 import org.onap.sdc.api.IDistributionClient;
48 import org.onap.sdc.api.consumer.IDistributionStatusMessage;
49 import org.onap.sdc.api.consumer.IFinalDistrStatusMessage;
50 import org.onap.sdc.api.notification.IArtifactInfo;
51 import org.onap.sdc.api.notification.INotificationData;
52 import org.onap.sdc.api.notification.IResourceInstance;
53 import org.onap.sdc.api.results.IDistributionClientDownloadResult;
54 import org.onap.sdc.api.results.IDistributionClientResult;
55 import org.onap.sdc.impl.DistributionClientFactory;
56 import org.onap.sdc.utils.DistributionActionResultEnum;
57 import org.onap.sdc.utils.DistributionStatusEnum;
58 import org.onap.so.asdc.activity.DeployActivitySpecs;
59 import org.onap.so.asdc.client.exceptions.ASDCControllerException;
60 import org.onap.so.asdc.client.exceptions.ASDCDownloadException;
61 import org.onap.so.asdc.client.exceptions.ASDCParametersException;
62 import org.onap.so.asdc.client.exceptions.ArtifactInstallerException;
63 import org.onap.so.asdc.installer.IVfResourceInstaller;
64 import org.onap.so.asdc.installer.PnfResourceStructure;
65 import org.onap.so.asdc.installer.ResourceStructure;
66 import org.onap.so.asdc.installer.ResourceType;
67 import org.onap.so.asdc.installer.ToscaResourceStructure;
68 import org.onap.so.asdc.installer.VfResourceStructure;
69 import org.onap.so.asdc.installer.heat.ToscaResourceInstaller;
70 import org.onap.so.asdc.tenantIsolation.DistributionStatus;
71 import org.onap.so.asdc.tenantIsolation.WatchdogDistribution;
72 import org.onap.so.asdc.util.ASDCNotificationLogging;
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.logging.filter.base.ErrorCode;
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 int getNbOfNotificationsOngoing() {
151 return nbOfNotificationsOngoing;
154 public IDistributionClient getDistributionClient() {
155 return distributionClient;
158 public void setDistributionClient(IDistributionClient distributionClient) {
159 this.distributionClient = distributionClient;
162 protected void changeControllerStatus(ASDCControllerStatus newControllerStatus) {
163 switch (newControllerStatus) {
166 ++this.nbOfNotificationsOngoing;
167 this.controllerStatus = newControllerStatus;
171 changeOnStatusIDLE(newControllerStatus);
175 this.controllerStatus = newControllerStatus;
181 private void changeOnStatusIDLE(ASDCControllerStatus newControllerStatus) {
182 if (this.nbOfNotificationsOngoing > 1) {
183 --this.nbOfNotificationsOngoing;
185 this.nbOfNotificationsOngoing = 0;
186 this.controllerStatus = newControllerStatus;
190 public ASDCControllerStatus getControllerStatus() {
191 return this.controllerStatus;
194 public String getControllerName() {
195 return controllerName;
198 public void setControllerName(String controllerName) {
199 this.controllerName = controllerName;
203 * This method initializes the ASDC Controller and the ASDC Client.
205 * @throws ASDCControllerException It throws an exception if the ASDC Client cannot be instantiated or if an init
206 * attempt is done when already initialized
207 * @throws ASDCParametersException If there is an issue with the parameters provided
208 * @throws IOException In case of issues when trying to load the key file
210 public void initASDC() throws ASDCControllerException {
211 logger.debug("Initialize the ASDC Controller");
213 throw new ASDCControllerException("The controller is already initialized, call the closeASDC method first");
216 if (asdcConfig != null) {
217 asdcConfig.setAsdcControllerName(controllerName);
220 if (this.distributionClient == null) {
221 distributionClient = DistributionClientFactory.createDistributionClient();
224 IDistributionClientResult result =
225 this.distributionClient.init(asdcConfig, asdcNotificationCallBack, asdcStatusCallBack);
226 if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
228 "ASDC distribution client init failed with reason:" + result.getDistributionMessageResult();
229 logger.debug(endEvent);
230 this.changeControllerStatus(ASDCControllerStatus.STOPPED);
231 throw new ASDCControllerException("Initialization of the ASDC Controller failed with reason: "
232 + result.getDistributionMessageResult());
235 result = this.distributionClient.start();
236 if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
238 "ASDC distribution client start failed with reason:" + result.getDistributionMessageResult();
239 logger.debug(endEvent);
240 this.changeControllerStatus(ASDCControllerStatus.STOPPED);
241 throw new ASDCControllerException(
242 "Startup of the ASDC Controller failed with reason: " + result.getDistributionMessageResult());
245 this.changeControllerStatus(ASDCControllerStatus.IDLE);
246 logger.info(LoggingAnchor.THREE, MessageEnum.ASDC_INIT_ASDC_CLIENT_SUC.toString(), "ASDC",
247 "changeControllerStatus");
251 * @return true if controller is stopped
253 public boolean isStopped() {
254 return this.getControllerStatus() == ASDCControllerStatus.STOPPED;
258 * This method closes the ASDC Controller and the ASDC Client.
260 * @throws ASDCControllerException It throws an exception if the ASDC Client cannot be closed because it's currently
261 * BUSY in processing notifications.
263 public void closeASDC() throws ASDCControllerException {
266 throw new ASDCControllerException("Cannot close the ASDC controller as it's currently in BUSY state");
268 if (this.distributionClient != null) {
269 this.distributionClient.stop();
270 // If auto managed we can set it to Null, ASDCController controls it.
271 // In the other case the client of this class has specified it, so we can't reset it
272 if (isAsdcClientAutoManaged) {
273 // Next init will initialize it with a new ASDC Client
274 this.distributionClient = null;
278 this.changeControllerStatus(ASDCControllerStatus.STOPPED);
282 * @return true if controller is currently processing notification
284 public boolean isBusy() {
285 return this.getControllerStatus() == ASDCControllerStatus.BUSY;
288 protected boolean checkResourceAlreadyDeployed(ResourceStructure resource, boolean serviceDeployed)
289 throws ArtifactInstallerException {
292 if (toscaInstaller.isResourceAlreadyDeployed(resource, serviceDeployed)) {
293 logger.info(LoggingAnchor.FOUR, MessageEnum.ASDC_ARTIFACT_ALREADY_EXIST.toString(),
294 resource.getResourceInstance().getResourceInstanceName(),
295 resource.getResourceInstance().getResourceUUID(), resource.getResourceInstance().getResourceName());
297 this.sendDeployNotificationsForResource(resource, DistributionStatusEnum.ALREADY_DOWNLOADED, null);
298 this.sendDeployNotificationsForResource(resource, DistributionStatusEnum.ALREADY_DEPLOYED, null);
306 protected void notifyErrorToAsdc(INotificationData iNotif, ToscaResourceStructure toscaResourceStructure,
307 DistributionStatusEnum deployStatus, VfResourceStructure resourceStructure, String errorMessage) {
308 // do csar lever first
309 this.sendCsarDeployNotification(resourceStructure, toscaResourceStructure, deployStatus, errorMessage);
311 for (IResourceInstance resource : iNotif.getResources()) {
312 resourceStructure = new VfResourceStructure(iNotif, resource);
313 errorMessage = String.format("Resource with UUID: %s already exists", resource.getResourceUUID());
314 this.sendCsarDeployNotification(resourceStructure, toscaResourceStructure, deployStatus, errorMessage);
318 protected boolean isCsarAlreadyDeployed(INotificationData iNotif, ToscaResourceStructure toscaResourceStructure) {
319 VfResourceStructure resourceStructure = null;
320 String errorMessage = "";
321 boolean csarAlreadyDeployed = false;
322 DistributionStatusEnum deployStatus = DistributionStatusEnum.DEPLOY_OK;
323 WatchdogComponentDistributionStatus wdStatus =
324 new WatchdogComponentDistributionStatus(iNotif.getDistributionID(), MSO);
326 csarAlreadyDeployed = toscaInstaller.isCsarAlreadyDeployed(toscaResourceStructure);
327 if (csarAlreadyDeployed) {
328 deployStatus = DistributionStatusEnum.ALREADY_DEPLOYED;
329 resourceStructure = new VfResourceStructure(iNotif, null);
330 errorMessage = String.format("Csar with UUID: %s already exists",
331 toscaResourceStructure.getToscaArtifact().getArtifactUUID());
332 wdStatus.setComponentDistributionStatus(DistributionStatusEnum.COMPONENT_DONE_OK.name());
333 watchdogCDStatusRepository.saveAndFlush(wdStatus);
334 logger.error(errorMessage);
336 } catch (ArtifactInstallerException e) {
337 deployStatus = DistributionStatusEnum.DEPLOY_ERROR;
338 resourceStructure = new VfResourceStructure(iNotif, null);
339 errorMessage = e.getMessage();
340 wdStatus.setComponentDistributionStatus(DistributionStatusEnum.COMPONENT_DONE_ERROR.name());
341 watchdogCDStatusRepository.saveAndFlush(wdStatus);
342 logger.warn("Tosca Checksums don't match, Tosca validation check failed", e);
345 if (deployStatus != DistributionStatusEnum.DEPLOY_OK) {
346 notifyErrorToAsdc(iNotif, toscaResourceStructure, deployStatus, resourceStructure, errorMessage);
349 return csarAlreadyDeployed;
352 protected IDistributionClientDownloadResult downloadTheArtifact(IArtifactInfo artifact, String distributionId)
353 throws ASDCDownloadException {
355 logger.info("Trying to download the artifact UUID: {} from URL: {}", artifact.getArtifactUUID(),
356 artifact.getArtifactURL());
357 IDistributionClientDownloadResult downloadResult;
360 downloadResult = distributionClient.download(artifact);
361 if (null == downloadResult) {
362 logger.info(LoggingAnchor.TWO, MessageEnum.ASDC_ARTIFACT_NULL.toString(), artifact.getArtifactUUID());
363 return downloadResult;
365 } catch (RuntimeException e) {
366 logger.debug("Not able to download the artifact due to an exception: " + artifact.getArtifactURL());
367 this.sendASDCNotification(NotificationType.DOWNLOAD, artifact.getArtifactURL(), asdcConfig.getConsumerID(),
368 distributionId, DistributionStatusEnum.DOWNLOAD_ERROR, e.getMessage(), System.currentTimeMillis());
370 throw new ASDCDownloadException("Exception caught when downloading the artifact", e);
373 if (DistributionActionResultEnum.SUCCESS.equals(downloadResult.getDistributionActionResult())) {
374 logger.info(LoggingAnchor.FOUR, MessageEnum.ASDC_ARTIFACT_DOWNLOAD_SUC.toString(),
375 artifact.getArtifactURL(), artifact.getArtifactUUID(), downloadResult.getArtifactPayload().length);
378 logger.error(LoggingAnchor.SEVEN, MessageEnum.ASDC_ARTIFACT_DOWNLOAD_FAIL.toString(),
379 artifact.getArtifactName(), artifact.getArtifactURL(), artifact.getArtifactUUID(),
380 downloadResult.getDistributionMessageResult(), ErrorCode.DataError.getValue(),
381 "ASDC artifact download fail");
383 this.sendASDCNotification(NotificationType.DOWNLOAD, artifact.getArtifactURL(), asdcConfig.getConsumerID(),
384 distributionId, DistributionStatusEnum.DOWNLOAD_ERROR,
385 downloadResult.getDistributionMessageResult(), System.currentTimeMillis());
387 throw new ASDCDownloadException("Artifact " + artifact.getArtifactName()
388 + " could not be downloaded from ASDC URL " + artifact.getArtifactURL() + UUID_PARAM
389 + artifact.getArtifactUUID() + ")" + System.lineSeparator() + "Error message is "
390 + downloadResult.getDistributionMessageResult() + System.lineSeparator());
394 this.sendASDCNotification(NotificationType.DOWNLOAD, artifact.getArtifactURL(), asdcConfig.getConsumerID(),
395 distributionId, DistributionStatusEnum.DOWNLOAD_OK, null, System.currentTimeMillis());
396 return downloadResult;
400 private void writeArtifactToFile(IArtifactInfo artifact, IDistributionClientDownloadResult resultArtifact) {
403 Paths.get(getMsoConfigPath(), "ASDC", artifact.getArtifactVersion(), artifact.getArtifactName())
404 .normalize().toString();
406 logger.info("Trying to write artifact UUID: {}, URL: {} to file: {}", artifact.getArtifactUUID(),
407 artifact.getArtifactURL(), filePath);
409 // make parent directory
410 File file = new File(filePath);
411 File fileParent = file.getParentFile();
412 if (!fileParent.exists()) {
416 byte[] payloadBytes = resultArtifact.getArtifactPayload();
418 try (FileOutputStream outFile = new FileOutputStream(filePath)) {
419 logger.info(LoggingAnchor.FOUR, MessageEnum.ASDC_RECEIVE_SERVICE_NOTIF.toString(),
420 "***WRITE FILE ARTIFACT NAME", "ASDC", artifact.getArtifactName());
421 outFile.write(payloadBytes, 0, payloadBytes.length);
422 } catch (Exception e) {
423 logger.debug("Exception :", e);
424 logger.error(LoggingAnchor.SEVEN, MessageEnum.ASDC_ARTIFACT_DOWNLOAD_FAIL.toString(),
425 artifact.getArtifactName(), artifact.getArtifactURL(), artifact.getArtifactUUID(),
426 resultArtifact.getDistributionMessageResult(), ErrorCode.DataError.getValue(),
427 "ASDC write to file failed");
433 protected void sendDeployNotificationsForResource(ResourceStructure resourceStructure,
434 DistributionStatusEnum distribStatus, String errorReason) {
436 for (IArtifactInfo artifactInfo : resourceStructure.getResourceInstance().getArtifacts()) {
438 if ((DistributionStatusEnum.DEPLOY_OK.equals(distribStatus)
439 && !("OTHER").equalsIgnoreCase(artifactInfo.getArtifactType())
440 && !resourceStructure.isAlreadyDeployed())
441 // This could be NULL if the artifact is a VF module artifact, this won't be present in the MAP
442 && resourceStructure.getArtifactsMapByUUID().get(artifactInfo.getArtifactUUID()) != null
443 && resourceStructure.getArtifactsMapByUUID().get(artifactInfo.getArtifactUUID())
444 .getDeployedInDb() == 0) {
445 this.sendASDCNotification(NotificationType.DEPLOY, artifactInfo.getArtifactURL(),
446 asdcConfig.getConsumerID(), resourceStructure.getNotification().getDistributionID(),
447 DistributionStatusEnum.DEPLOY_ERROR,
448 "The artifact has not been used by the modules defined in the resource",
449 System.currentTimeMillis());
451 this.sendASDCNotification(NotificationType.DEPLOY, artifactInfo.getArtifactURL(),
452 asdcConfig.getConsumerID(), resourceStructure.getNotification().getDistributionID(),
453 distribStatus, errorReason, System.currentTimeMillis());
458 protected void sendCsarDeployNotification(ResourceStructure resourceStructure,
459 ToscaResourceStructure toscaResourceStructure, DistributionStatusEnum statusEnum, String errorReason) {
461 IArtifactInfo csarArtifact = toscaResourceStructure.getToscaArtifact();
463 this.sendASDCNotification(NotificationType.DEPLOY, csarArtifact.getArtifactURL(), asdcConfig.getConsumerID(),
464 resourceStructure.getNotification().getDistributionID(), statusEnum, errorReason,
465 System.currentTimeMillis());
469 protected void deployResourceStructure(ResourceStructure resourceStructure,
470 ToscaResourceStructure toscaResourceStructure) throws ArtifactInstallerException {
472 logger.info(LoggingAnchor.FOUR, MessageEnum.ASDC_START_DEPLOY_ARTIFACT.toString(),
473 resourceStructure.getResourceInstance().getResourceInstanceName(),
474 resourceStructure.getResourceInstance().getResourceUUID(), "ASDC");
476 resourceStructure.prepareInstall();
477 toscaInstaller.installTheResource(toscaResourceStructure, resourceStructure);
479 } catch (ArtifactInstallerException e) {
480 logger.info(LoggingAnchor.SIX, MessageEnum.ASDC_ARTIFACT_DOWNLOAD_FAIL.toString(),
481 resourceStructure.getResourceInstance().getResourceName(),
482 resourceStructure.getResourceInstance().getResourceUUID(), resourceStructure.getNumberOfResources(),
483 "ASDC", "deployResourceStructure");
484 sendDeployNotificationsForResource(resourceStructure, DistributionStatusEnum.DEPLOY_ERROR, e.getMessage());
488 if (resourceStructure.isDeployedSuccessfully() || toscaResourceStructure.isDeployedSuccessfully()) {
489 logger.info(LoggingAnchor.SIX, MessageEnum.ASDC_ARTIFACT_DEPLOY_SUC.toString(),
490 resourceStructure.getResourceInstance().getResourceName(),
491 resourceStructure.getResourceInstance().getResourceUUID(), resourceStructure.getNumberOfResources(),
492 "ASDC", "deployResourceStructure");
493 sendDeployNotificationsForResource(resourceStructure, DistributionStatusEnum.DEPLOY_OK, null);
499 private enum NotificationType {
503 protected void sendASDCNotification(NotificationType notificationType, String artifactURL, String consumerID,
504 String distributionID, DistributionStatusEnum status, String errorReason, long timestamp) {
506 String event = "Sending " + notificationType.name() + "(" + status.name() + ")"
507 + " notification to ASDC for artifact:" + artifactURL;
509 if (errorReason != null) {
510 event = event + "(" + errorReason + ")";
512 logger.info(LoggingAnchor.SIX, MessageEnum.ASDC_SEND_NOTIF_ASDC.toString(), notificationType.name(),
513 status.name(), artifactURL, "ASDC", "sendASDCNotification");
518 IDistributionStatusMessage message =
519 new DistributionStatusMessage(artifactURL, consumerID, distributionID, status, timestamp);
520 if (errorReason != null) {
521 sendNotificationWithMessageAndErrorReason(notificationType, errorReason, message);
523 sendNotificationWithMessage(notificationType, message);
525 } catch (RuntimeException e) {
526 logger.warn(LoggingAnchor.FIVE, MessageEnum.ASDC_SEND_NOTIF_ASDC_EXEC.toString(), "ASDC",
527 "sendASDCNotification", ErrorCode.SchemaError.getValue(), "RuntimeException - sendASDCNotification",
532 private void sendNotificationWithMessage(NotificationType notificationType, IDistributionStatusMessage message) {
533 switch (notificationType) {
535 this.distributionClient.sendDownloadStatus(message);
538 this.distributionClient.sendDeploymentStatus(message);
545 private void sendNotificationWithMessageAndErrorReason(NotificationType notificationType, String errorReason,
546 IDistributionStatusMessage message) {
547 switch (notificationType) {
549 this.distributionClient.sendDownloadStatus(message, errorReason);
552 this.distributionClient.sendDeploymentStatus(message, errorReason);
559 protected void sendFinalDistributionStatus(String distributionID, DistributionStatusEnum status,
560 String errorReason) {
562 logger.debug("Enter sendFinalDistributionStatus with DistributionID " + distributionID + " and Status of "
563 + status.name() + " and ErrorReason " + errorReason);
565 long subStarttime = System.currentTimeMillis();
568 IFinalDistrStatusMessage finalDistribution = new FinalDistributionStatusMessage(distributionID, status,
569 subStarttime, asdcConfig.getConsumerID());
571 if (errorReason == null) {
572 this.distributionClient.sendFinalDistrStatus(finalDistribution);
574 this.distributionClient.sendFinalDistrStatus(finalDistribution, errorReason);
578 } catch (RuntimeException e) {
579 logger.debug("Exception caught in sendFinalDistributionStatus {}", e.getMessage());
580 logger.warn(LoggingAnchor.FIVE, MessageEnum.ASDC_SEND_NOTIF_ASDC_EXEC.toString(), "ASDC",
581 "sendASDCNotification", ErrorCode.SchemaError.getValue(), "RuntimeException - sendASDCNotification",
586 private Optional<String> getNotificationJson(INotificationData iNotif) {
587 ObjectMapper mapper = new ObjectMapper();
588 mapper.setSerializationInclusion(Include.NON_NULL);
589 mapper.setSerializationInclusion(Include.NON_EMPTY);
590 mapper.setSerializationInclusion(Include.NON_ABSENT);
591 mapper.enable(MapperFeature.USE_ANNOTATIONS);
592 mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
593 Optional<String> returnValue = Optional.empty();
595 returnValue = Optional.of(mapper.writeValueAsString(iNotif));
596 } catch (JsonProcessingException e) {
597 logger.error("Error converting incoming ASDC notification to JSON", e);
602 public void treatNotification(INotificationData iNotif) {
604 int noOfArtifacts = 0;
606 for (IResourceInstance resource : iNotif.getResources()) {
607 noOfArtifacts += resource.getArtifacts().size();
609 logger.info(LoggingAnchor.FOUR, MessageEnum.ASDC_RECEIVE_CALLBACK_NOTIF.toString(), noOfArtifacts,
610 iNotif.getServiceUUID(), "ASDC");
613 if (iNotif.getDistributionID() != null && !iNotif.getDistributionID().isEmpty()) {
614 MDC.put(ONAPLogConstants.MDCs.REQUEST_ID, iNotif.getDistributionID());
616 logger.debug(ASDCNotificationLogging.dumpASDCNotification(iNotif));
617 logger.info(LoggingAnchor.FOUR, MessageEnum.ASDC_RECEIVE_SERVICE_NOTIF.toString(), iNotif.getServiceUUID(),
618 "ASDC", "treatNotification");
620 this.changeControllerStatus(ASDCControllerStatus.BUSY);
621 Optional<String> notificationMessage = getNotificationJson(iNotif);
622 toscaInstaller.processWatchdog(iNotif.getDistributionID(), iNotif.getServiceUUID(), notificationMessage,
623 asdcConfig.getConsumerID());
625 // Process only the Resource artifacts in MSO
626 this.processResourceNotification(iNotif);
628 // ********************************************************************************************************
629 // Start Watchdog loop and wait for all components to complete before reporting final status back.
630 // **If timer expires first then we will report a Distribution Error back to ASDC
631 // ********************************************************************************************************
632 long initialStartTime = System.currentTimeMillis();
633 boolean componentsComplete = false;
634 String distributionStatus = null;
635 String watchdogError = null;
636 String overallStatus = null;
637 int watchDogTimeout = asdcConfig.getWatchDogTimeout() * 1000;
638 boolean isDeploySuccess = false;
640 while (!componentsComplete && (System.currentTimeMillis() - initialStartTime) < watchDogTimeout) {
643 distributionStatus = wd.getOverallDistributionStatus(iNotif.getDistributionID());
644 Thread.sleep(watchDogTimeout / 10);
645 } catch (Exception e) {
646 logger.debug("Exception in Watchdog Loop {}", e.getMessage());
647 Thread.sleep(watchDogTimeout / 10);
650 if (distributionStatus != null
651 && !distributionStatus.equalsIgnoreCase(DistributionStatus.INCOMPLETE.name())) {
653 if (distributionStatus.equalsIgnoreCase(DistributionStatus.SUCCESS.name())) {
654 isDeploySuccess = true;
655 overallStatus = DistributionStatusEnum.DISTRIBUTION_COMPLETE_OK.name();
657 overallStatus = DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name();
659 componentsComplete = true;
663 if (!componentsComplete) {
664 logger.debug("Timeout of {} seconds was reached before all components reported status",
666 watchdogError = "Timeout occurred while waiting for all components to report status";
667 overallStatus = DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name();
670 if (distributionStatus == null) {
671 overallStatus = DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name();
672 logger.debug("DistributionStatus is null for DistributionId: {}", iNotif.getDistributionID());
676 wd.executePatchAAI(iNotif.getDistributionID(), iNotif.getServiceInvariantUUID(), overallStatus);
677 logger.debug("A&AI Updated succefully with Distribution Status!");
678 } catch (Exception e) {
679 logger.debug("Exception in Watchdog executePatchAAI(): {}", e.getMessage());
680 watchdogError = "Error calling A&AI " + e.getMessage();
681 if (e.getCause() != null) {
682 logger.debug("Exception caused by: {}", e.getCause().getMessage());
686 wd.updateCatalogDBStatus(iNotif.getServiceInvariantUUID(), overallStatus);
688 if (isDeploySuccess && watchdogError == null) {
689 sendFinalDistributionStatus(iNotif.getDistributionID(), DistributionStatusEnum.DISTRIBUTION_COMPLETE_OK,
691 WatchdogDistributionStatus wds = new WatchdogDistributionStatus(iNotif.getDistributionID());
692 wds.setDistributionIdStatus(DistributionStatusEnum.DISTRIBUTION_COMPLETE_OK.toString());
695 sendFinalDistributionStatus(iNotif.getDistributionID(),
696 DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR, watchdogError);
697 WatchdogDistributionStatus wds = new WatchdogDistributionStatus(iNotif.getDistributionID());
698 wds.setDistributionIdStatus(DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.toString());
702 } catch (ObjectOptimisticLockingFailureException e) {
705 "OptimisticLockingFailure for DistributionId: {} Another process "
706 + "has already altered this distribution, so not going to process it on this site.",
707 iNotif.getDistributionID());
708 logger.error(LoggingAnchor.FIVE, MessageEnum.ASDC_GENERAL_EXCEPTION_ARG.toString(),
709 "Database concurrency exception: ", "ASDC", "treatNotification",
710 ErrorCode.BusinessProcessError.getValue(), "RuntimeException in treatNotification", e);
712 } catch (Exception e) {
713 logger.error("", MessageEnum.ASDC_GENERAL_EXCEPTION_ARG.toString(),
714 "Unexpected exception caught during the notification processing", "ASDC", "treatNotification",
715 ErrorCode.SchemaError.getValue(), "RuntimeException in treatNotification", e);
718 wd.executePatchAAI(iNotif.getDistributionID(), iNotif.getServiceInvariantUUID(),
719 DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name());
720 logger.debug("A&AI Updated succefully with Distribution Status of {}",
721 DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name());
722 } catch (Exception aaiException) {
723 logger.debug("Exception in executePatchAAI(): {}", aaiException);
724 if (aaiException.getCause() != null) {
725 logger.debug("Exception caused by: {}", aaiException.getCause().getMessage());
729 sendFinalDistributionStatus(iNotif.getDistributionID(), DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR,
732 WatchdogDistributionStatus wds = new WatchdogDistributionStatus(iNotif.getDistributionID());
733 wds.setDistributionIdStatus(DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.toString());
737 this.changeControllerStatus(ASDCControllerStatus.IDLE);
741 protected void processResourceNotification(INotificationData iNotif) {
742 // For each artifact, create a structure describing the VFModule in a ordered flat level
743 ResourceStructure resourceStructure = null;
744 String msoConfigPath = getMsoConfigPath();
745 ToscaResourceStructure toscaResourceStructure = new ToscaResourceStructure(msoConfigPath);
746 DistributionStatusEnum deployStatus = DistributionStatusEnum.DEPLOY_OK;
747 String errorMessage = null;
748 boolean serviceDeployed = false;
751 this.processCsarServiceArtifacts(iNotif, toscaResourceStructure);
752 if (isCsarAlreadyDeployed(iNotif, toscaResourceStructure)) {
755 // process NsstResource
756 this.processNsstNotification(iNotif, toscaResourceStructure);
758 if (iNotif.getResources().isEmpty()) {
759 logger.error("Service Model contains no resources.");
763 for (IResourceInstance resource : iNotif.getResources()) {
765 String resourceType = resource.getResourceType();
766 boolean hasVFResource = false;
768 logger.info("Processing Resource Type: {}, Model UUID: {}", resourceType, resource.getResourceUUID());
770 resourceStructure = getResourceStructure(iNotif, resource, resourceType);
774 if (!this.checkResourceAlreadyDeployed(resourceStructure, serviceDeployed)) {
775 logger.debug("Processing Resource Type: " + resourceType + " and Model UUID: "
776 + resourceStructure.getResourceInstance().getResourceUUID());
779 if ("VF".equals(resourceType)) {
780 hasVFResource = true;
781 for (IArtifactInfo artifact : resource.getArtifacts()) {
782 IDistributionClientDownloadResult resultArtifact =
783 this.downloadTheArtifact(artifact, iNotif.getDistributionID());
784 if (resultArtifact == null) {
788 if (ASDCConfiguration.VF_MODULES_METADATA.equals(artifact.getArtifactType())) {
789 logger.debug("VF_MODULE_ARTIFACT: "
790 + new String(resultArtifact.getArtifactPayload(), StandardCharsets.UTF_8));
791 logger.debug(ASDCNotificationLogging
792 .dumpVfModuleMetaDataList(((VfResourceStructure) resourceStructure)
793 .decodeVfModuleArtifact(resultArtifact.getArtifactPayload())));
795 if (!ASDCConfiguration.WORKFLOW.equals(artifact.getArtifactType())) {
796 resourceStructure.addArtifactToStructure(distributionClient, artifact,
799 writeArtifactToFile(artifact, resultArtifact);
801 "Adding workflow artifact to structure: " + artifact.getArtifactName());
802 resourceStructure.addWorkflowArtifactToStructure(artifact, resultArtifact);
807 // Deploy VF resource and artifacts
808 logger.debug("Preparing to deploy Service: {}", iNotif.getServiceUUID());
811 this.deployResourceStructure(resourceStructure, toscaResourceStructure);
812 serviceDeployed = true;
816 } catch (ArtifactInstallerException e) {
817 deployStatus = DistributionStatusEnum.DEPLOY_ERROR;
818 errorMessage = e.getMessage();
819 logger.error("Exception occurred", e);
822 if (!hasVFResource) {
824 logger.debug("No resources found for Service: " + iNotif.getServiceUUID());
826 logger.debug("Preparing to deploy Service: {}", iNotif.getServiceUUID());
828 this.deployResourceStructure(resourceStructure, toscaResourceStructure);
829 serviceDeployed = true;
830 } catch (ArtifactInstallerException e) {
831 deployStatus = DistributionStatusEnum.DEPLOY_ERROR;
832 errorMessage = e.getMessage();
833 logger.error("Exception occurred", e);
838 this.sendCsarDeployNotification(resourceStructure, toscaResourceStructure, deployStatus, errorMessage);
840 } catch (ASDCDownloadException | UnsupportedEncodingException e) {
841 logger.error(LoggingAnchor.SIX, MessageEnum.ASDC_GENERAL_EXCEPTION_ARG.toString(),
842 "Exception caught during Installation of artifact", "ASDC", "processResourceNotification",
843 ErrorCode.BusinessProcessError.getValue(), "Exception in processResourceNotification", e);
847 private ResourceStructure getResourceStructure(INotificationData iNotif, IResourceInstance resource,
848 String resourceType) {
849 if ("VF".equals(resourceType)) {
850 return new VfResourceStructure(iNotif, resource);
852 if ("PNF".equals(resourceType)) {
853 return new PnfResourceStructure(iNotif, resource);
855 logger.info("No resources found for Service: {}", iNotif.getServiceUUID());
856 ResourceStructure resourceStructure = new VfResourceStructure(iNotif, new ResourceInstance());
857 resourceStructure.setResourceType(ResourceType.OTHER);
858 return resourceStructure;
861 private String getMsoConfigPath() {
862 String msoConfigPath = System.getProperty("mso.config.path");
863 if (msoConfigPath == null) {
864 logger.info("Unable to find the system property mso.config.path, use the default configuration");
865 msoConfigPath = asdcConfig.getPropertyOrNull("mso.config.defaultpath");
867 if (msoConfigPath == null) {
868 logger.info("Unable to find the property: {} from configuration.", "mso.config.defaultpath");
871 logger.info("MSO config path is: {}", msoConfigPath);
872 return msoConfigPath;
875 protected void processCsarServiceArtifacts(INotificationData iNotif,
876 ToscaResourceStructure toscaResourceStructure) {
878 List<IArtifactInfo> serviceArtifacts = iNotif.getServiceArtifacts();
880 for (IArtifactInfo artifact : serviceArtifacts) {
882 if (artifact.getArtifactType().equals(ASDCConfiguration.TOSCA_CSAR)) {
886 toscaResourceStructure.setToscaArtifact(artifact);
888 IDistributionClientDownloadResult resultArtifact =
889 this.downloadTheArtifact(artifact, iNotif.getDistributionID());
891 writeArtifactToFile(artifact, resultArtifact);
893 toscaResourceStructure.updateResourceStructure(artifact);
895 toscaResourceStructure.setServiceVersion(iNotif.getServiceVersion());
897 logger.debug(ASDCNotificationLogging.dumpCSARNotification(iNotif, toscaResourceStructure));
900 } catch (Exception e) {
901 logger.error(LoggingAnchor.SIX, MessageEnum.ASDC_GENERAL_EXCEPTION_ARG.toString(),
902 "Exception caught during processCsarServiceArtifacts", "ASDC",
903 "processCsarServiceArtifacts", ErrorCode.BusinessProcessError.getValue(),
904 "Exception in processCsarServiceArtifacts", e);
906 } else if (artifact.getArtifactType().equals(ASDCConfiguration.WORKFLOW)) {
910 IDistributionClientDownloadResult resultArtifact =
911 this.downloadTheArtifact(artifact, iNotif.getDistributionID());
913 writeArtifactToFile(artifact, resultArtifact);
915 toscaResourceStructure.setToscaArtifact(artifact);
917 logger.debug(ASDCNotificationLogging.dumpASDCNotification(iNotif));
920 } catch (Exception e) {
921 logger.info("Whats the error {}", e.getMessage());
922 logger.error(LoggingAnchor.SIX, MessageEnum.ASDC_GENERAL_EXCEPTION_ARG.toString(),
923 "Exception caught during processCsarServiceArtifacts", "ASDC",
924 "processCsarServiceArtifacts", ErrorCode.BusinessProcessError.getValue(),
925 "Exception in processCsarServiceArtifacts", e);
927 } else if (artifact.getArtifactType().equals(ASDCConfiguration.OTHER)) {
929 IDistributionClientDownloadResult resultArtifact =
930 this.downloadTheArtifact(artifact, iNotif.getDistributionID());
932 writeArtifactToFile(artifact, resultArtifact);
934 toscaResourceStructure.setToscaArtifact(artifact);
936 toscaResourceStructure.setServiceVersion(iNotif.getServiceVersion());
938 } catch (ASDCDownloadException e) {
939 logger.error(LoggingAnchor.SIX, MessageEnum.ASDC_GENERAL_EXCEPTION_ARG.toString(),
940 "Exception caught during processCsarServiceArtifacts", "ASDC",
941 "processCsarServiceArtifacts", ErrorCode.BusinessProcessError.getValue(),
942 "Exception in processCsarServiceArtifacts", e);
952 * @return the address of the ASDC we are connected to.
954 public String getAddress() {
955 if (asdcConfig != null) {
956 return asdcConfig.getAsdcAddress();
962 * @return the environment name of the ASDC we are connected to.
964 public String getEnvironment() {
965 if (asdcConfig != null) {
966 return asdcConfig.getEnvironmentName();
971 private void processNsstNotification(INotificationData iNotif, ToscaResourceStructure toscaResourceStructure) {
972 Metadata serviceMetadata = toscaResourceStructure.getServiceMetadata();
974 String category = serviceMetadata.getValue(SdcPropertyNames.PROPERTY_NAME_CATEGORY);
975 boolean isNeedInital = (category.contains("NSST") || category.equalsIgnoreCase("TN Network Requirement"))
976 && iNotif.getResources().isEmpty();
978 String artifactContent = null;
979 List<IArtifactInfo> serviceArtifacts = iNotif.getServiceArtifacts();
980 Optional<IArtifactInfo> artifactOpt = serviceArtifacts.stream()
981 .filter(e -> e.getArtifactType().equalsIgnoreCase("OTHER")).findFirst();
982 if (artifactOpt.isPresent()) {
983 IArtifactInfo artifactInfo = artifactOpt.get();
984 logger.debug("Ready to parse this serviceArtifactUUID: " + artifactInfo.getArtifactUUID());
985 String filePath = Paths.get(getMsoConfigPath(), "ASDC", artifactInfo.getArtifactVersion(),
986 artifactInfo.getArtifactName()).normalize().toString();
987 ZipParser zipParserInstance = ZipParser.getInstance();
988 artifactContent = zipParserInstance.parseJsonForZip(filePath);
990 "serviceArtifact parsing success! serviceArtifactUUID: " + artifactInfo.getArtifactUUID());
992 ResourceStructure resourceStructure = new VfResourceStructure(iNotif, new ResourceInstance());
993 resourceStructure.setResourceType(ResourceType.OTHER);
994 toscaInstaller.installNsstService(toscaResourceStructure, (VfResourceStructure) resourceStructure,
997 logger.debug("serviceArtifact is null");
998 toscaInstaller.installNsstService(toscaResourceStructure, null, null);
1003 } catch (IOException e) {
1004 logger.error("serviceArtifact parse failure for service uuid: "
1005 + serviceMetadata.getValue(SdcPropertyNames.PROPERTY_NAME_CATEGORY));
1006 } catch (Exception e) {
1007 logger.error("error NSST process resource failure ", e);