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 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 * ============LICENSE_END=========================================================
24 package org.onap.so.asdc.client;
27 import com.fasterxml.jackson.annotation.JsonInclude.Include;
28 import com.fasterxml.jackson.core.JsonProcessingException;
29 import com.fasterxml.jackson.databind.DeserializationFeature;
30 import com.fasterxml.jackson.databind.MapperFeature;
31 import com.fasterxml.jackson.databind.ObjectMapper;
33 import java.io.FileOutputStream;
34 import java.io.IOException;
35 import java.io.UnsupportedEncodingException;
36 import java.nio.file.Paths;
37 import java.util.List;
38 import java.util.Optional;
39 import org.onap.so.logger.LoggingAnchor;
40 import org.onap.logging.ref.slf4j.ONAPLogConstants;
41 import org.onap.sdc.api.IDistributionClient;
42 import org.onap.sdc.api.consumer.IDistributionStatusMessage;
43 import org.onap.sdc.api.consumer.IFinalDistrStatusMessage;
44 import org.onap.sdc.api.notification.IArtifactInfo;
45 import org.onap.sdc.api.notification.INotificationData;
46 import org.onap.sdc.api.notification.IResourceInstance;
47 import org.onap.sdc.api.results.IDistributionClientDownloadResult;
48 import org.onap.sdc.api.results.IDistributionClientResult;
49 import org.onap.sdc.impl.DistributionClientFactory;
50 import org.onap.sdc.utils.DistributionActionResultEnum;
51 import org.onap.sdc.utils.DistributionStatusEnum;
52 import org.onap.so.asdc.activity.DeployActivitySpecs;
53 import org.onap.so.asdc.client.exceptions.ASDCControllerException;
54 import org.onap.so.asdc.client.exceptions.ASDCDownloadException;
55 import org.onap.so.asdc.client.exceptions.ASDCParametersException;
56 import org.onap.so.asdc.client.exceptions.ArtifactInstallerException;
57 import org.onap.so.asdc.installer.IVfResourceInstaller;
58 import org.onap.so.asdc.installer.PnfResourceStructure;
59 import org.onap.so.asdc.installer.ResourceStructure;
60 import org.onap.so.asdc.installer.ResourceType;
61 import org.onap.so.asdc.installer.ToscaResourceStructure;
62 import org.onap.so.asdc.installer.VfResourceStructure;
63 import org.onap.so.asdc.installer.heat.ToscaResourceInstaller;
64 import org.onap.so.asdc.tenantIsolation.DistributionStatus;
65 import org.onap.so.asdc.tenantIsolation.WatchdogDistribution;
66 import org.onap.so.asdc.util.ASDCNotificationLogging;
67 import org.onap.so.db.request.beans.WatchdogComponentDistributionStatus;
68 import org.onap.so.db.request.beans.WatchdogDistributionStatus;
69 import org.onap.so.db.request.data.repository.WatchdogComponentDistributionStatusRepository;
70 import org.onap.so.db.request.data.repository.WatchdogDistributionStatusRepository;
71 import org.onap.so.logger.ErrorCode;
72 import org.onap.so.logger.MessageEnum;
73 import org.slf4j.Logger;
74 import org.slf4j.LoggerFactory;
76 import org.springframework.beans.factory.annotation.Autowired;
77 import org.springframework.orm.ObjectOptimisticLockingFailureException;
78 import org.springframework.stereotype.Component;
81 public class ASDCController {
83 protected static final Logger logger = LoggerFactory.getLogger(ASDCController.class);
85 private static final String UNKNOWN = "Unknown";
87 protected boolean isAsdcClientAutoManaged = false;
89 protected String controllerName;
91 private ASDCControllerStatus controllerStatus = ASDCControllerStatus.STOPPED;
93 protected int nbOfNotificationsOngoing = 0;
96 private ToscaResourceInstaller toscaInstaller;
99 private WatchdogDistributionStatusRepository wdsRepo;
102 protected WatchdogComponentDistributionStatusRepository watchdogCDStatusRepository;
105 private ASDCConfiguration asdcConfig;
108 private ASDCStatusCallBack asdcStatusCallBack;
111 private ASDCNotificationCallBack asdcNotificationCallBack;
113 private IDistributionClient distributionClient;
115 private static final String UUID_PARAM = "(UUID:";
117 protected static final String MSO = "SO";
120 private WatchdogDistribution wd;
123 DeployActivitySpecs deployActivitySpecs;
125 public ASDCController() {
129 public ASDCController(String controllerConfigName) {
130 isAsdcClientAutoManaged = true;
131 this.controllerName = controllerConfigName;
134 public ASDCController(String controllerConfigName, IDistributionClient asdcClient,
135 IVfResourceInstaller resourceinstaller) {
136 distributionClient = asdcClient;
139 public ASDCController(String controllerConfigName, IDistributionClient asdcClient) {
140 distributionClient = asdcClient;
141 this.controllerName = controllerConfigName;
144 public int getNbOfNotificationsOngoing() {
145 return nbOfNotificationsOngoing;
148 public IDistributionClient getDistributionClient() {
149 return distributionClient;
152 public void setDistributionClient(IDistributionClient distributionClient) {
153 this.distributionClient = distributionClient;
156 protected void changeControllerStatus(ASDCControllerStatus newControllerStatus) {
157 switch (newControllerStatus) {
160 ++this.nbOfNotificationsOngoing;
161 this.controllerStatus = newControllerStatus;
165 if (this.nbOfNotificationsOngoing > 1) {
166 --this.nbOfNotificationsOngoing;
168 this.nbOfNotificationsOngoing = 0;
169 this.controllerStatus = newControllerStatus;
174 this.controllerStatus = newControllerStatus;
180 public ASDCControllerStatus getControllerStatus() {
181 return this.controllerStatus;
184 public String getControllerName() {
185 return controllerName;
188 public void setControllerName(String controllerName) {
189 this.controllerName = controllerName;
193 * This method initializes the ASDC Controller and the ASDC Client.
195 * @throws ASDCControllerException It throws an exception if the ASDC Client cannot be instantiated or if an init
196 * attempt is done when already initialized
197 * @throws ASDCParametersException If there is an issue with the parameters provided
198 * @throws IOException In case of issues when trying to load the key file
200 public void initASDC() throws ASDCControllerException {
201 logger.debug("Initialize the ASDC Controller");
203 throw new ASDCControllerException("The controller is already initialized, call the closeASDC method first");
206 if (asdcConfig != null) {
207 asdcConfig.setAsdcControllerName(controllerName);
210 if (this.distributionClient == null) {
211 distributionClient = DistributionClientFactory.createDistributionClient();
214 IDistributionClientResult result =
215 this.distributionClient.init(asdcConfig, asdcNotificationCallBack, asdcStatusCallBack);
216 if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
218 "ASDC distribution client init failed with reason:" + result.getDistributionMessageResult();
219 logger.debug(endEvent);
220 this.changeControllerStatus(ASDCControllerStatus.STOPPED);
221 throw new ASDCControllerException("Initialization of the ASDC Controller failed with reason: "
222 + result.getDistributionMessageResult());
225 result = this.distributionClient.start();
226 if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
228 "ASDC distribution client start failed with reason:" + result.getDistributionMessageResult();
229 logger.debug(endEvent);
230 this.changeControllerStatus(ASDCControllerStatus.STOPPED);
231 throw new ASDCControllerException(
232 "Startup of the ASDC Controller failed with reason: " + result.getDistributionMessageResult());
235 this.changeControllerStatus(ASDCControllerStatus.IDLE);
236 logger.info(LoggingAnchor.THREE, MessageEnum.ASDC_INIT_ASDC_CLIENT_SUC.toString(), "ASDC",
237 "changeControllerStatus");
241 * @return true if controller is stopped
243 public boolean isStopped() {
244 return this.getControllerStatus() == ASDCControllerStatus.STOPPED;
248 * This method closes the ASDC Controller and the ASDC Client.
250 * @throws ASDCControllerException It throws an exception if the ASDC Client cannot be closed because it's currently
251 * BUSY in processing notifications.
253 public void closeASDC() throws ASDCControllerException {
256 throw new ASDCControllerException("Cannot close the ASDC controller as it's currently in BUSY state");
258 if (this.distributionClient != null) {
259 this.distributionClient.stop();
260 // If auto managed we can set it to Null, ASDCController controls it.
261 // In the other case the client of this class has specified it, so we can't reset it
262 if (isAsdcClientAutoManaged) {
263 // Next init will initialize it with a new ASDC Client
264 this.distributionClient = null;
268 this.changeControllerStatus(ASDCControllerStatus.STOPPED);
272 * @return true if controller is currently processing notification
274 public boolean isBusy() {
275 return this.getControllerStatus() == ASDCControllerStatus.BUSY;
278 protected boolean checkResourceAlreadyDeployed(ResourceStructure resource, boolean serviceDeployed)
279 throws ArtifactInstallerException {
282 if (toscaInstaller.isResourceAlreadyDeployed(resource, serviceDeployed)) {
283 logger.info(LoggingAnchor.FOUR, MessageEnum.ASDC_ARTIFACT_ALREADY_EXIST.toString(),
284 resource.getResourceInstance().getResourceInstanceName(),
285 resource.getResourceInstance().getResourceUUID(), resource.getResourceInstance().getResourceName());
287 this.sendDeployNotificationsForResource(resource, DistributionStatusEnum.ALREADY_DOWNLOADED, null);
288 this.sendDeployNotificationsForResource(resource, DistributionStatusEnum.ALREADY_DEPLOYED, null);
296 protected void notifyErrorToAsdc(INotificationData iNotif, ToscaResourceStructure toscaResourceStructure,
297 DistributionStatusEnum deployStatus, VfResourceStructure resourceStructure, String errorMessage) {
298 // do csar lever first
299 this.sendCsarDeployNotification(iNotif, resourceStructure, toscaResourceStructure, deployStatus, errorMessage);
301 for (IResourceInstance resource : iNotif.getResources()) {
302 resourceStructure = new VfResourceStructure(iNotif, resource);
303 errorMessage = String.format("Resource with UUID: %s already exists", resource.getResourceUUID());
304 this.sendCsarDeployNotification(iNotif, resourceStructure, toscaResourceStructure, deployStatus,
309 protected boolean isCsarAlreadyDeployed(INotificationData iNotif, ToscaResourceStructure toscaResourceStructure) {
310 VfResourceStructure resourceStructure = null;
311 String errorMessage = "";
312 boolean csarAlreadyDeployed = false;
313 DistributionStatusEnum deployStatus = DistributionStatusEnum.DEPLOY_OK;
314 WatchdogComponentDistributionStatus wdStatus =
315 new WatchdogComponentDistributionStatus(iNotif.getDistributionID(), MSO);
317 csarAlreadyDeployed = toscaInstaller.isCsarAlreadyDeployed(toscaResourceStructure);
318 if (csarAlreadyDeployed) {
319 deployStatus = DistributionStatusEnum.ALREADY_DEPLOYED;
320 resourceStructure = new VfResourceStructure(iNotif, null);
321 errorMessage = String.format("Csar with UUID: %s already exists",
322 toscaResourceStructure.getToscaArtifact().getArtifactUUID());
323 wdStatus.setComponentDistributionStatus(DistributionStatusEnum.COMPONENT_DONE_OK.name());
324 watchdogCDStatusRepository.saveAndFlush(wdStatus);
325 logger.error(errorMessage);
327 } catch (ArtifactInstallerException e) {
328 deployStatus = DistributionStatusEnum.DEPLOY_ERROR;
329 resourceStructure = new VfResourceStructure(iNotif, null);
330 errorMessage = e.getMessage();
331 wdStatus.setComponentDistributionStatus(DistributionStatusEnum.COMPONENT_DONE_ERROR.name());
332 watchdogCDStatusRepository.saveAndFlush(wdStatus);
333 logger.warn("Tosca Checksums don't match, Tosca validation check failed", e);
336 if (deployStatus != DistributionStatusEnum.DEPLOY_OK) {
337 notifyErrorToAsdc(iNotif, toscaResourceStructure, deployStatus, resourceStructure, errorMessage);
340 return csarAlreadyDeployed;
343 protected IDistributionClientDownloadResult downloadTheArtifact(IArtifactInfo artifact, String distributionId)
344 throws ASDCDownloadException {
346 logger.info("Trying to download the artifact UUID: {} from URL: {}", artifact.getArtifactUUID(),
347 artifact.getArtifactURL());
348 IDistributionClientDownloadResult downloadResult;
351 downloadResult = distributionClient.download(artifact);
352 if (null == downloadResult) {
353 logger.info(LoggingAnchor.TWO, MessageEnum.ASDC_ARTIFACT_NULL.toString(), artifact.getArtifactUUID());
354 return downloadResult;
356 } catch (RuntimeException e) {
357 logger.debug("Not able to download the artifact due to an exception: " + artifact.getArtifactURL());
358 this.sendASDCNotification(NotificationType.DOWNLOAD, artifact.getArtifactURL(), asdcConfig.getConsumerID(),
359 distributionId, DistributionStatusEnum.DOWNLOAD_ERROR, e.getMessage(), System.currentTimeMillis());
361 throw new ASDCDownloadException("Exception caught when downloading the artifact", e);
364 if (DistributionActionResultEnum.SUCCESS.equals(downloadResult.getDistributionActionResult())) {
365 logger.info(LoggingAnchor.FOUR, MessageEnum.ASDC_ARTIFACT_DOWNLOAD_SUC.toString(),
366 artifact.getArtifactURL(), artifact.getArtifactUUID(),
367 String.valueOf(downloadResult.getArtifactPayload().length));
370 logger.error(LoggingAnchor.SEVEN, MessageEnum.ASDC_ARTIFACT_DOWNLOAD_FAIL.toString(),
371 artifact.getArtifactName(), artifact.getArtifactURL(), artifact.getArtifactUUID(),
372 downloadResult.getDistributionMessageResult(), ErrorCode.DataError.getValue(),
373 "ASDC artifact download fail");
375 this.sendASDCNotification(NotificationType.DOWNLOAD, artifact.getArtifactURL(), asdcConfig.getConsumerID(),
376 distributionId, DistributionStatusEnum.DOWNLOAD_ERROR,
377 downloadResult.getDistributionMessageResult(), System.currentTimeMillis());
379 throw new ASDCDownloadException("Artifact " + artifact.getArtifactName()
380 + " could not be downloaded from ASDC URL " + artifact.getArtifactURL() + UUID_PARAM
381 + artifact.getArtifactUUID() + ")" + System.lineSeparator() + "Error message is "
382 + downloadResult.getDistributionMessageResult() + System.lineSeparator());
386 this.sendASDCNotification(NotificationType.DOWNLOAD, artifact.getArtifactURL(), asdcConfig.getConsumerID(),
387 distributionId, DistributionStatusEnum.DOWNLOAD_OK, null, System.currentTimeMillis());
388 return downloadResult;
392 private void writeArtifactToFile(IArtifactInfo artifact, IDistributionClientDownloadResult resultArtifact) {
395 Paths.get(getMsoConfigPath(), "ASDC", artifact.getArtifactVersion(), artifact.getArtifactName())
396 .normalize().toString();
398 logger.info("Trying to write artifact UUID: {}, URL: {} to file: {}", artifact.getArtifactUUID(),
399 artifact.getArtifactURL(), filePath);
401 // make parent directory
402 File file = new File(filePath);
403 File fileParent = file.getParentFile();
404 if (!fileParent.exists()) {
408 byte[] payloadBytes = resultArtifact.getArtifactPayload();
410 try (FileOutputStream outFile = new FileOutputStream(filePath)) {
411 logger.info(LoggingAnchor.FOUR, MessageEnum.ASDC_RECEIVE_SERVICE_NOTIF.toString(),
412 "***WRITE FILE ARTIFACT NAME", "ASDC", artifact.getArtifactName());
413 outFile.write(payloadBytes, 0, payloadBytes.length);
414 } catch (Exception e) {
415 logger.debug("Exception :", e);
416 logger.error(LoggingAnchor.SEVEN, MessageEnum.ASDC_ARTIFACT_DOWNLOAD_FAIL.toString(),
417 artifact.getArtifactName(), artifact.getArtifactURL(), artifact.getArtifactUUID(),
418 resultArtifact.getDistributionMessageResult(), ErrorCode.DataError.getValue(),
419 "ASDC write to file failed");
425 protected void sendDeployNotificationsForResource(ResourceStructure resourceStructure,
426 DistributionStatusEnum distribStatus, String errorReason) {
428 for (IArtifactInfo artifactInfo : resourceStructure.getResourceInstance().getArtifacts()) {
430 if ((DistributionStatusEnum.DEPLOY_OK.equals(distribStatus)
431 && !("OTHER").equalsIgnoreCase(artifactInfo.getArtifactType())
432 && !resourceStructure.isAlreadyDeployed())
433 // This could be NULL if the artifact is a VF module artifact, this won't be present in the MAP
434 && resourceStructure.getArtifactsMapByUUID().get(artifactInfo.getArtifactUUID()) != null
435 && resourceStructure.getArtifactsMapByUUID().get(artifactInfo.getArtifactUUID())
436 .getDeployedInDb() == 0) {
437 this.sendASDCNotification(NotificationType.DEPLOY, artifactInfo.getArtifactURL(),
438 asdcConfig.getConsumerID(), resourceStructure.getNotification().getDistributionID(),
439 DistributionStatusEnum.DEPLOY_ERROR,
440 "The artifact has not been used by the modules defined in the resource",
441 System.currentTimeMillis());
443 this.sendASDCNotification(NotificationType.DEPLOY, artifactInfo.getArtifactURL(),
444 asdcConfig.getConsumerID(), resourceStructure.getNotification().getDistributionID(),
445 distribStatus, errorReason, System.currentTimeMillis());
450 protected void sendCsarDeployNotification(INotificationData iNotif, ResourceStructure resourceStructure,
451 ToscaResourceStructure toscaResourceStructure, DistributionStatusEnum statusEnum, String errorReason) {
453 IArtifactInfo csarArtifact = toscaResourceStructure.getToscaArtifact();
455 this.sendASDCNotification(NotificationType.DEPLOY, csarArtifact.getArtifactURL(), asdcConfig.getConsumerID(),
456 resourceStructure.getNotification().getDistributionID(), statusEnum, errorReason,
457 System.currentTimeMillis());
461 protected void deployResourceStructure(ResourceStructure resourceStructure,
462 ToscaResourceStructure toscaResourceStructure) throws ArtifactInstallerException {
464 logger.info(LoggingAnchor.FOUR, MessageEnum.ASDC_START_DEPLOY_ARTIFACT.toString(),
465 resourceStructure.getResourceInstance().getResourceInstanceName(),
466 resourceStructure.getResourceInstance().getResourceUUID(), "ASDC");
468 resourceStructure.prepareInstall();
469 toscaInstaller.installTheResource(toscaResourceStructure, resourceStructure);
471 } catch (ArtifactInstallerException e) {
472 logger.info(LoggingAnchor.SIX, MessageEnum.ASDC_ARTIFACT_DOWNLOAD_FAIL.toString(),
473 resourceStructure.getResourceInstance().getResourceName(),
474 resourceStructure.getResourceInstance().getResourceUUID(),
475 String.valueOf(resourceStructure.getNumberOfResources()), "ASDC", "deployResourceStructure");
476 sendDeployNotificationsForResource(resourceStructure, DistributionStatusEnum.DEPLOY_ERROR, e.getMessage());
480 if (resourceStructure.isDeployedSuccessfully() || toscaResourceStructure.isDeployedSuccessfully()) {
481 logger.info(LoggingAnchor.SIX, MessageEnum.ASDC_ARTIFACT_DEPLOY_SUC.toString(),
482 resourceStructure.getResourceInstance().getResourceName(),
483 resourceStructure.getResourceInstance().getResourceUUID(),
484 String.valueOf(resourceStructure.getNumberOfResources()), "ASDC", "deployResourceStructure");
485 sendDeployNotificationsForResource(resourceStructure, DistributionStatusEnum.DEPLOY_OK, null);
491 private enum NotificationType {
495 protected void sendASDCNotification(NotificationType notificationType, String artifactURL, String consumerID,
496 String distributionID, DistributionStatusEnum status, String errorReason, long timestamp) {
498 String event = "Sending " + notificationType.name() + "(" + status.name() + ")"
499 + " notification to ASDC for artifact:" + artifactURL;
501 if (errorReason != null) {
502 event = event + "(" + errorReason + ")";
504 logger.info(LoggingAnchor.SIX, MessageEnum.ASDC_SEND_NOTIF_ASDC.toString(), notificationType.name(),
505 status.name(), artifactURL, "ASDC", "sendASDCNotification");
510 IDistributionStatusMessage message =
511 new DistributionStatusMessage(artifactURL, consumerID, distributionID, status, timestamp);
513 switch (notificationType) {
515 if (errorReason != null) {
516 this.distributionClient.sendDownloadStatus(message, errorReason);
518 this.distributionClient.sendDownloadStatus(message);
523 if (errorReason != null) {
524 this.distributionClient.sendDeploymentStatus(message, errorReason);
526 this.distributionClient.sendDeploymentStatus(message);
533 } catch (RuntimeException e) {
534 logger.warn(LoggingAnchor.FIVE, MessageEnum.ASDC_SEND_NOTIF_ASDC_EXEC.toString(), "ASDC",
535 "sendASDCNotification", ErrorCode.SchemaError.getValue(), "RuntimeException - sendASDCNotification",
540 protected void sendFinalDistributionStatus(String distributionID, DistributionStatusEnum status,
541 String errorReason) {
543 logger.debug("Enter sendFinalDistributionStatus with DistributionID " + distributionID + " and Status of "
544 + status.name() + " and ErrorReason " + errorReason);
546 long subStarttime = System.currentTimeMillis();
549 IFinalDistrStatusMessage finalDistribution = new FinalDistributionStatusMessage(distributionID, status,
550 subStarttime, asdcConfig.getConsumerID());
552 if (errorReason == null) {
553 this.distributionClient.sendFinalDistrStatus(finalDistribution);
555 this.distributionClient.sendFinalDistrStatus(finalDistribution, errorReason);
559 } catch (RuntimeException e) {
560 logger.debug("Exception caught in sendFinalDistributionStatus {}", e.getMessage());
561 logger.warn(LoggingAnchor.FIVE, MessageEnum.ASDC_SEND_NOTIF_ASDC_EXEC.toString(), "ASDC",
562 "sendASDCNotification", ErrorCode.SchemaError.getValue(), "RuntimeException - sendASDCNotification",
567 private Optional<String> getNotificationJson(INotificationData iNotif) {
568 ObjectMapper mapper = new ObjectMapper();
569 mapper.setSerializationInclusion(Include.NON_NULL);
570 mapper.setSerializationInclusion(Include.NON_EMPTY);
571 mapper.setSerializationInclusion(Include.NON_ABSENT);
572 mapper.enable(MapperFeature.USE_ANNOTATIONS);
573 mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
574 Optional<String> returnValue = Optional.empty();
576 returnValue = Optional.of(mapper.writeValueAsString(iNotif));
577 } catch (JsonProcessingException e) {
578 logger.error("Error converting incoming ASDC notification to JSON", e);
583 public void treatNotification(INotificationData iNotif) {
585 int noOfArtifacts = 0;
587 for (IResourceInstance resource : iNotif.getResources()) {
588 noOfArtifacts += resource.getArtifacts().size();
590 logger.info(LoggingAnchor.FOUR, MessageEnum.ASDC_RECEIVE_CALLBACK_NOTIF.toString(),
591 String.valueOf(noOfArtifacts), iNotif.getServiceUUID(), "ASDC");
594 if (iNotif.getDistributionID() != null && !iNotif.getDistributionID().isEmpty()) {
595 MDC.put(ONAPLogConstants.MDCs.REQUEST_ID, iNotif.getDistributionID());
597 logger.debug(ASDCNotificationLogging.dumpASDCNotification(iNotif));
598 logger.info(LoggingAnchor.FOUR, MessageEnum.ASDC_RECEIVE_SERVICE_NOTIF.toString(), iNotif.getServiceUUID(),
599 "ASDC", "treatNotification");
601 this.changeControllerStatus(ASDCControllerStatus.BUSY);
602 Optional<String> notificationMessage = getNotificationJson(iNotif);
603 toscaInstaller.processWatchdog(iNotif.getDistributionID(), iNotif.getServiceUUID(), notificationMessage,
604 asdcConfig.getConsumerID());
606 // Process only the Resource artifacts in MSO
607 this.processResourceNotification(iNotif);
609 // ********************************************************************************************************
610 // Start Watchdog loop and wait for all components to complete before reporting final status back.
611 // **If timer expires first then we will report a Distribution Error back to ASDC
612 // ********************************************************************************************************
613 long initialStartTime = System.currentTimeMillis();
614 boolean componentsComplete = false;
615 String distributionStatus = null;
616 String watchdogError = null;
617 String overallStatus = null;
618 int watchDogTimeout = asdcConfig.getWatchDogTimeout() * 1000;
619 boolean isDeploySuccess = false;
621 while (!componentsComplete && (System.currentTimeMillis() - initialStartTime) < watchDogTimeout) {
624 distributionStatus = wd.getOverallDistributionStatus(iNotif.getDistributionID());
625 Thread.sleep(watchDogTimeout / 10);
626 } catch (Exception e) {
627 logger.debug("Exception in Watchdog Loop {}", e.getMessage());
628 Thread.sleep(watchDogTimeout / 10);
631 if (distributionStatus != null
632 && !distributionStatus.equalsIgnoreCase(DistributionStatus.INCOMPLETE.name())) {
634 if (distributionStatus.equalsIgnoreCase(DistributionStatus.SUCCESS.name())) {
635 isDeploySuccess = true;
636 overallStatus = DistributionStatusEnum.DISTRIBUTION_COMPLETE_OK.name();
638 overallStatus = DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name();
640 componentsComplete = true;
644 if (!componentsComplete) {
645 logger.debug("Timeout of {} seconds was reached before all components reported status",
647 watchdogError = "Timeout occurred while waiting for all components to report status";
648 overallStatus = DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name();
651 if (distributionStatus == null) {
652 overallStatus = DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name();
653 logger.debug("DistributionStatus is null for DistributionId: {}", iNotif.getDistributionID());
657 wd.executePatchAAI(iNotif.getDistributionID(), iNotif.getServiceInvariantUUID(), overallStatus);
658 logger.debug("A&AI Updated succefully with Distribution Status!");
659 } catch (Exception e) {
660 logger.debug("Exception in Watchdog executePatchAAI(): {}", e.getMessage());
661 watchdogError = "Error calling A&AI " + e.getMessage();
662 if (e.getCause() != null) {
663 logger.debug("Exception caused by: {}", e.getCause().getMessage());
667 wd.updateCatalogDBStatus(iNotif.getServiceInvariantUUID(), overallStatus);
669 if (isDeploySuccess && watchdogError == null) {
670 sendFinalDistributionStatus(iNotif.getDistributionID(), DistributionStatusEnum.DISTRIBUTION_COMPLETE_OK,
672 WatchdogDistributionStatus wds = new WatchdogDistributionStatus(iNotif.getDistributionID());
673 wds.setDistributionIdStatus(DistributionStatusEnum.DISTRIBUTION_COMPLETE_OK.toString());
676 sendFinalDistributionStatus(iNotif.getDistributionID(),
677 DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR, watchdogError);
678 WatchdogDistributionStatus wds = new WatchdogDistributionStatus(iNotif.getDistributionID());
679 wds.setDistributionIdStatus(DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.toString());
683 } catch (ObjectOptimisticLockingFailureException e) {
686 "OptimisticLockingFailure for DistributionId: {} Another process "
687 + "has already altered this distribution, so not going to process it on this site.",
688 iNotif.getDistributionID());
689 logger.error(LoggingAnchor.FIVE, MessageEnum.ASDC_GENERAL_EXCEPTION_ARG.toString(),
690 "Database concurrency exception: ", "ASDC", "treatNotification",
691 ErrorCode.BusinessProcesssError.getValue(), "RuntimeException in treatNotification", e);
693 } catch (Exception e) {
694 logger.error("", MessageEnum.ASDC_GENERAL_EXCEPTION_ARG.toString(),
695 "Unexpected exception caught during the notification processing", "ASDC", "treatNotification",
696 ErrorCode.SchemaError.getValue(), "RuntimeException in treatNotification", e);
699 wd.executePatchAAI(iNotif.getDistributionID(), iNotif.getServiceInvariantUUID(),
700 DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name());
701 logger.debug("A&AI Updated succefully with Distribution Status of {}",
702 DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name());
703 } catch (Exception aaiException) {
704 logger.debug("Exception in executePatchAAI(): {}", aaiException);
705 if (aaiException.getCause() != null) {
706 logger.debug("Exception caused by: {}", aaiException.getCause().getMessage());
710 sendFinalDistributionStatus(iNotif.getDistributionID(), DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR,
713 WatchdogDistributionStatus wds = new WatchdogDistributionStatus(iNotif.getDistributionID());
714 wds.setDistributionIdStatus(DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.toString());
718 this.changeControllerStatus(ASDCControllerStatus.IDLE);
722 protected void processResourceNotification(INotificationData iNotif) {
723 // For each artifact, create a structure describing the VFModule in a ordered flat level
724 ResourceStructure resourceStructure = null;
725 String msoConfigPath = getMsoConfigPath();
726 boolean hasVFResource = false;
727 ToscaResourceStructure toscaResourceStructure = new ToscaResourceStructure(msoConfigPath);
728 DistributionStatusEnum deployStatus = DistributionStatusEnum.DEPLOY_OK;
729 String errorMessage = null;
730 boolean serviceDeployed = false;
733 this.processCsarServiceArtifacts(iNotif, toscaResourceStructure);
734 if (isCsarAlreadyDeployed(iNotif, toscaResourceStructure)) {
738 for (IResourceInstance resource : iNotif.getResources()) {
740 String resourceType = resource.getResourceType();
743 logger.info("Processing Resource Type: {}, Model UUID: {}", resourceType, resource.getResourceUUID());
745 if ("VF".equals(resourceType)) {
746 resourceStructure = new VfResourceStructure(iNotif, resource);
747 } else if ("PNF".equals(resourceType)) {
748 resourceStructure = new PnfResourceStructure(iNotif, resource);
750 // There are cases where the Service has no VF resources, those are handled here
751 logger.info("No resources found for Service: {}", iNotif.getServiceUUID());
752 resourceStructure = new VfResourceStructure(iNotif, new ResourceInstance());
753 resourceStructure.setResourceType(ResourceType.OTHER);
758 if (!this.checkResourceAlreadyDeployed(resourceStructure, serviceDeployed)) {
760 logger.debug("Processing Resource Type: " + resourceType + " and Model UUID: "
761 + resourceStructure.getResourceInstance().getResourceUUID());
764 if ("VF".equals(resourceType)) {
765 hasVFResource = true;
766 for (IArtifactInfo artifact : resource.getArtifacts()) {
767 IDistributionClientDownloadResult resultArtifact =
768 this.downloadTheArtifact(artifact, iNotif.getDistributionID());
769 if (resultArtifact != null) {
771 if (ASDCConfiguration.VF_MODULES_METADATA.equals(artifact.getArtifactType())) {
772 logger.debug("VF_MODULE_ARTIFACT: "
773 + new String(resultArtifact.getArtifactPayload(), "UTF-8"));
774 logger.debug(ASDCNotificationLogging
775 .dumpVfModuleMetaDataList(((VfResourceStructure) resourceStructure)
776 .decodeVfModuleArtifact(resultArtifact.getArtifactPayload())));
778 if (!ASDCConfiguration.WORKFLOW.equals(artifact.getArtifactType())) {
779 resourceStructure.addArtifactToStructure(distributionClient, artifact,
782 writeArtifactToFile(artifact, resultArtifact);
784 "Adding workflow artifact to structure: " + artifact.getArtifactName());
785 resourceStructure.addWorkflowArtifactToStructure(artifact, resultArtifact);
790 // Deploy VF resource and artifacts
791 logger.debug("Preparing to deploy Service: {}", iNotif.getServiceUUID());
794 this.deployResourceStructure(resourceStructure, toscaResourceStructure);
795 serviceDeployed = true;
799 } catch (ArtifactInstallerException e) {
800 deployStatus = DistributionStatusEnum.DEPLOY_ERROR;
801 errorMessage = e.getMessage();
802 logger.error("Exception occurred", e);
806 if (!hasVFResource) {
808 logger.debug("No resources found for Service: " + iNotif.getServiceUUID());
810 logger.debug("Preparing to deploy Service: {}", iNotif.getServiceUUID());
812 this.deployResourceStructure(resourceStructure, toscaResourceStructure);
813 } catch (ArtifactInstallerException e) {
814 deployStatus = DistributionStatusEnum.DEPLOY_ERROR;
815 errorMessage = e.getMessage();
816 logger.error("Exception occurred", e);
820 this.sendCsarDeployNotification(iNotif, resourceStructure, toscaResourceStructure, deployStatus,
823 } catch (ASDCDownloadException | UnsupportedEncodingException e) {
824 logger.error(LoggingAnchor.SIX, MessageEnum.ASDC_GENERAL_EXCEPTION_ARG.toString(),
825 "Exception caught during Installation of artifact", "ASDC", "processResourceNotification",
826 ErrorCode.BusinessProcesssError.getValue(), "Exception in processResourceNotification", e);
830 private String getMsoConfigPath() {
831 String msoConfigPath = System.getProperty("mso.config.path");
832 if (msoConfigPath == null) {
833 logger.info("Unable to find the system property mso.config.path, use the default configuration");
834 msoConfigPath = asdcConfig.getPropertyOrNull("mso.config.defaultpath");
836 if (msoConfigPath == null) {
837 logger.info("Unable to find the property: {} from configuration.", "mso.config.defaultpath");
840 logger.info("MSO config path is: {}", msoConfigPath);
841 return msoConfigPath;
844 protected void processCsarServiceArtifacts(INotificationData iNotif,
845 ToscaResourceStructure toscaResourceStructure) {
847 List<IArtifactInfo> serviceArtifacts = iNotif.getServiceArtifacts();
849 for (IArtifactInfo artifact : serviceArtifacts) {
851 if (artifact.getArtifactType().equals(ASDCConfiguration.TOSCA_CSAR)) {
855 toscaResourceStructure.setToscaArtifact(artifact);
857 IDistributionClientDownloadResult resultArtifact =
858 this.downloadTheArtifact(artifact, iNotif.getDistributionID());
860 writeArtifactToFile(artifact, resultArtifact);
862 toscaResourceStructure.updateResourceStructure(artifact);
864 toscaResourceStructure.setServiceVersion(iNotif.getServiceVersion());
866 logger.debug(ASDCNotificationLogging.dumpCSARNotification(iNotif, toscaResourceStructure));
869 } catch (Exception e) {
870 logger.error(LoggingAnchor.SIX, MessageEnum.ASDC_GENERAL_EXCEPTION_ARG.toString(),
871 "Exception caught during processCsarServiceArtifacts", "ASDC",
872 "processCsarServiceArtifacts", ErrorCode.BusinessProcesssError.getValue(),
873 "Exception in processCsarServiceArtifacts", e);
875 } else if (artifact.getArtifactType().equals(ASDCConfiguration.WORKFLOW)) {
879 IDistributionClientDownloadResult resultArtifact =
880 this.downloadTheArtifact(artifact, iNotif.getDistributionID());
882 writeArtifactToFile(artifact, resultArtifact);
884 toscaResourceStructure.setToscaArtifact(artifact);
886 logger.debug(ASDCNotificationLogging.dumpASDCNotification(iNotif));
889 } catch (Exception e) {
890 logger.info("Whats the error {}", e.getMessage());
891 logger.error(LoggingAnchor.SIX, MessageEnum.ASDC_GENERAL_EXCEPTION_ARG.toString(),
892 "Exception caught during processCsarServiceArtifacts", "ASDC",
893 "processCsarServiceArtifacts", ErrorCode.BusinessProcesssError.getValue(),
894 "Exception in processCsarServiceArtifacts", e);
905 * @return the address of the ASDC we are connected to.
907 public String getAddress() {
908 if (asdcConfig != null) {
909 return asdcConfig.getAsdcAddress();
915 * @return the environment name of the ASDC we are connected to.
917 public String getEnvironment() {
918 if (asdcConfig != null) {
919 return asdcConfig.getEnvironmentName();