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.sdc.api.IDistributionClient;
40 import org.onap.sdc.api.consumer.IDistributionStatusMessage;
41 import org.onap.sdc.api.consumer.IFinalDistrStatusMessage;
42 import org.onap.sdc.api.notification.IArtifactInfo;
43 import org.onap.sdc.api.notification.INotificationData;
44 import org.onap.sdc.api.notification.IResourceInstance;
45 import org.onap.sdc.api.results.IDistributionClientDownloadResult;
46 import org.onap.sdc.api.results.IDistributionClientResult;
47 import org.onap.sdc.impl.DistributionClientFactory;
48 import org.onap.sdc.utils.DistributionActionResultEnum;
49 import org.onap.sdc.utils.DistributionStatusEnum;
50 import org.onap.so.asdc.activity.DeployActivitySpecs;
51 import org.onap.so.asdc.client.exceptions.ASDCControllerException;
52 import org.onap.so.asdc.client.exceptions.ASDCDownloadException;
53 import org.onap.so.asdc.client.exceptions.ASDCParametersException;
54 import org.onap.so.asdc.client.exceptions.ArtifactInstallerException;
55 import org.onap.so.asdc.installer.IVfResourceInstaller;
56 import org.onap.so.asdc.installer.PnfResourceStructure;
57 import org.onap.so.asdc.installer.ResourceStructure;
58 import org.onap.so.asdc.installer.ResourceType;
59 import org.onap.so.asdc.installer.ToscaResourceStructure;
60 import org.onap.so.asdc.installer.VfResourceStructure;
61 import org.onap.so.asdc.installer.heat.ToscaResourceInstaller;
62 import org.onap.so.asdc.tenantIsolation.DistributionStatus;
63 import org.onap.so.asdc.tenantIsolation.WatchdogDistribution;
64 import org.onap.so.asdc.util.ASDCNotificationLogging;
65 import org.onap.so.db.request.beans.WatchdogComponentDistributionStatus;
66 import org.onap.so.db.request.beans.WatchdogDistributionStatus;
67 import org.onap.so.db.request.data.repository.WatchdogComponentDistributionStatusRepository;
68 import org.onap.so.db.request.data.repository.WatchdogDistributionStatusRepository;
69 import org.onap.so.logger.ErrorCode;
70 import org.onap.so.logger.MessageEnum;
71 import org.slf4j.Logger;
72 import org.slf4j.LoggerFactory;
73 import org.springframework.beans.factory.annotation.Autowired;
74 import org.springframework.orm.ObjectOptimisticLockingFailureException;
75 import org.springframework.stereotype.Component;
78 public class ASDCController {
80 protected static final Logger logger = LoggerFactory.getLogger(ASDCController.class);
82 protected boolean isAsdcClientAutoManaged = false;
84 protected String controllerName;
86 private ASDCControllerStatus controllerStatus = ASDCControllerStatus.STOPPED;
88 protected int nbOfNotificationsOngoing = 0;
91 private ToscaResourceInstaller toscaInstaller;
94 private WatchdogDistributionStatusRepository wdsRepo;
97 protected WatchdogComponentDistributionStatusRepository watchdogCDStatusRepository;
100 private ASDCConfiguration asdcConfig;
103 private ASDCStatusCallBack asdcStatusCallBack;
106 private ASDCNotificationCallBack asdcNotificationCallBack;
108 private IDistributionClient distributionClient;
110 private static final String UUID_PARAM = "(UUID:";
112 protected static final String MSO = "SO";
115 private WatchdogDistribution wd;
118 DeployActivitySpecs deployActivitySpecs;
120 public int getNbOfNotificationsOngoing() {
121 return nbOfNotificationsOngoing;
124 public IDistributionClient getDistributionClient() {
125 return distributionClient;
128 public void setDistributionClient(IDistributionClient distributionClient) {
129 this.distributionClient = distributionClient;
132 protected void changeControllerStatus(ASDCControllerStatus newControllerStatus) {
133 switch (newControllerStatus) {
136 ++this.nbOfNotificationsOngoing;
137 this.controllerStatus = newControllerStatus;
141 if (this.nbOfNotificationsOngoing > 1) {
142 --this.nbOfNotificationsOngoing;
144 this.nbOfNotificationsOngoing = 0;
145 this.controllerStatus = newControllerStatus;
150 this.controllerStatus = newControllerStatus;
156 public ASDCControllerStatus getControllerStatus() {
157 return this.controllerStatus;
160 public ASDCController() {
164 public ASDCController(String controllerConfigName) {
165 isAsdcClientAutoManaged = true;
166 this.controllerName = controllerConfigName;
169 public ASDCController(String controllerConfigName, IDistributionClient asdcClient,
170 IVfResourceInstaller resourceinstaller) {
171 distributionClient = asdcClient;
174 public ASDCController(String controllerConfigName, IDistributionClient asdcClient) {
175 distributionClient = asdcClient;
176 this.controllerName = controllerConfigName;
179 public String getControllerName() {
180 return controllerName;
183 public void setControllerName(String controllerName) {
184 this.controllerName = controllerName;
188 * This method initializes the ASDC Controller and the ASDC Client.
190 * @throws ASDCControllerException It throws an exception if the ASDC Client cannot be instantiated or if an init
191 * attempt is done when already initialized
192 * @throws ASDCParametersException If there is an issue with the parameters provided
193 * @throws IOException In case of issues when trying to load the key file
195 public void initASDC() throws ASDCControllerException {
196 String event = "Initialize the ASDC Controller";
198 if (this.getControllerStatus() != ASDCControllerStatus.STOPPED) {
199 String endEvent = "The controller is already initialized, call the closeASDC method first";
200 throw new ASDCControllerException(endEvent);
203 if (asdcConfig != null) {
204 asdcConfig.setAsdcControllerName(controllerName);
207 if (this.distributionClient == null) {
208 distributionClient = DistributionClientFactory.createDistributionClient();
211 IDistributionClientResult result =
212 this.distributionClient.init(asdcConfig, asdcNotificationCallBack, asdcStatusCallBack);
213 if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
215 "ASDC distribution client init failed with reason:" + result.getDistributionMessageResult();
216 logger.debug(endEvent);
217 this.changeControllerStatus(ASDCControllerStatus.STOPPED);
218 throw new ASDCControllerException("Initialization of the ASDC Controller failed with reason: "
219 + result.getDistributionMessageResult());
222 result = this.distributionClient.start();
223 if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
225 "ASDC distribution client start failed with reason:" + result.getDistributionMessageResult();
226 logger.debug(endEvent);
227 this.changeControllerStatus(ASDCControllerStatus.STOPPED);
228 throw new ASDCControllerException(
229 "Startup of the ASDC Controller failed with reason: " + result.getDistributionMessageResult());
232 this.changeControllerStatus(ASDCControllerStatus.IDLE);
233 logger.info("{} {} {}", MessageEnum.ASDC_INIT_ASDC_CLIENT_SUC.toString(), "ASDC", "changeControllerStatus");
237 * This method closes the ASDC Controller and the ASDC Client.
239 * @throws ASDCControllerException It throws an exception if the ASDC Client cannot be closed because it's currently
240 * BUSY in processing notifications.
242 public void closeASDC() throws ASDCControllerException {
244 if (this.getControllerStatus() == ASDCControllerStatus.BUSY) {
245 throw new ASDCControllerException("Cannot close the ASDC controller as it's currently in BUSY state");
247 if (this.distributionClient != null) {
248 this.distributionClient.stop();
249 // If auto managed we can set it to Null, ASDCController controls it.
250 // In the other case the client of this class has specified it, so we can't reset it
251 if (isAsdcClientAutoManaged) {
252 // Next init will initialize it with a new ASDC Client
253 this.distributionClient = null;
257 this.changeControllerStatus(ASDCControllerStatus.STOPPED);
260 protected boolean checkResourceAlreadyDeployed(ResourceStructure resource, boolean serviceDeployed)
261 throws ArtifactInstallerException {
264 if (toscaInstaller.isResourceAlreadyDeployed(resource, serviceDeployed)) {
265 logger.info("{} {} {} {}", MessageEnum.ASDC_ARTIFACT_ALREADY_EXIST.toString(),
266 resource.getResourceInstance().getResourceInstanceName(),
267 resource.getResourceInstance().getResourceUUID(), resource.getResourceInstance().getResourceName());
269 this.sendDeployNotificationsForResource(resource, DistributionStatusEnum.ALREADY_DOWNLOADED, null);
270 this.sendDeployNotificationsForResource(resource, DistributionStatusEnum.ALREADY_DEPLOYED, null);
278 protected void notifyErrorToAsdc(INotificationData iNotif, ToscaResourceStructure toscaResourceStructure,
279 DistributionStatusEnum deployStatus, VfResourceStructure resourceStructure, String errorMessage) {
280 // do csar lever first
281 this.sendCsarDeployNotification(iNotif, resourceStructure, toscaResourceStructure, deployStatus, errorMessage);
283 for (IResourceInstance resource : iNotif.getResources()) {
284 resourceStructure = new VfResourceStructure(iNotif, resource);
285 errorMessage = String.format("Resource with UUID: %s already exists", resource.getResourceUUID());
286 this.sendCsarDeployNotification(iNotif, resourceStructure, toscaResourceStructure, deployStatus,
291 protected boolean isCsarAlreadyDeployed(INotificationData iNotif, ToscaResourceStructure toscaResourceStructure) {
292 VfResourceStructure resourceStructure = null;
293 String errorMessage = "";
294 boolean csarAlreadyDeployed = false;
295 DistributionStatusEnum deployStatus = DistributionStatusEnum.DEPLOY_OK;
296 WatchdogComponentDistributionStatus wdStatus =
297 new WatchdogComponentDistributionStatus(iNotif.getDistributionID(), MSO);
299 csarAlreadyDeployed = toscaInstaller.isCsarAlreadyDeployed(toscaResourceStructure);
300 if (csarAlreadyDeployed) {
301 deployStatus = DistributionStatusEnum.ALREADY_DEPLOYED;
302 resourceStructure = new VfResourceStructure(iNotif, null);
303 errorMessage = String.format("Csar with UUID: %s already exists",
304 toscaResourceStructure.getToscaArtifact().getArtifactUUID());
305 wdStatus.setComponentDistributionStatus(DistributionStatusEnum.COMPONENT_DONE_OK.name());
306 watchdogCDStatusRepository.saveAndFlush(wdStatus);
307 logger.error(errorMessage);
309 } catch (ArtifactInstallerException e) {
310 deployStatus = DistributionStatusEnum.DEPLOY_ERROR;
311 resourceStructure = new VfResourceStructure(iNotif, null);
312 errorMessage = e.getMessage();
313 wdStatus.setComponentDistributionStatus(DistributionStatusEnum.COMPONENT_DONE_ERROR.name());
314 watchdogCDStatusRepository.saveAndFlush(wdStatus);
315 logger.warn("Tosca Checksums don't match, Tosca validation check failed", e);
318 if (deployStatus != DistributionStatusEnum.DEPLOY_OK) {
319 notifyErrorToAsdc(iNotif, toscaResourceStructure, deployStatus, resourceStructure, errorMessage);
322 return csarAlreadyDeployed;
325 protected IDistributionClientDownloadResult downloadTheArtifact(IArtifactInfo artifact, String distributionId)
326 throws ASDCDownloadException {
328 logger.info("Trying to download the artifact UUID: {} from URL: {}", artifact.getArtifactUUID(),
329 artifact.getArtifactURL());
330 IDistributionClientDownloadResult downloadResult;
333 downloadResult = distributionClient.download(artifact);
334 if (null == downloadResult) {
335 logger.info("{} {}", MessageEnum.ASDC_ARTIFACT_NULL.toString(), artifact.getArtifactUUID());
336 return downloadResult;
338 } catch (RuntimeException e) {
339 logger.debug("Not able to download the artifact due to an exception: " + artifact.getArtifactURL());
340 this.sendASDCNotification(NotificationType.DOWNLOAD, artifact.getArtifactURL(), asdcConfig.getConsumerID(),
341 distributionId, DistributionStatusEnum.DOWNLOAD_ERROR, e.getMessage(), System.currentTimeMillis());
343 throw new ASDCDownloadException("Exception caught when downloading the artifact", e);
346 if (DistributionActionResultEnum.SUCCESS.equals(downloadResult.getDistributionActionResult())) {
347 logger.info("{} {} {} {}", MessageEnum.ASDC_ARTIFACT_DOWNLOAD_SUC.toString(), artifact.getArtifactURL(),
348 artifact.getArtifactUUID(), String.valueOf(downloadResult.getArtifactPayload().length));
351 logger.error("{} {} {} {} {} {} {}", MessageEnum.ASDC_ARTIFACT_DOWNLOAD_FAIL.toString(),
352 artifact.getArtifactName(), artifact.getArtifactURL(), artifact.getArtifactUUID(),
353 downloadResult.getDistributionMessageResult(), ErrorCode.DataError.getValue(),
354 "ASDC artifact download fail");
356 this.sendASDCNotification(NotificationType.DOWNLOAD, artifact.getArtifactURL(), asdcConfig.getConsumerID(),
357 distributionId, DistributionStatusEnum.DOWNLOAD_ERROR,
358 downloadResult.getDistributionMessageResult(), System.currentTimeMillis());
360 throw new ASDCDownloadException("Artifact " + artifact.getArtifactName()
361 + " could not be downloaded from ASDC URL " + artifact.getArtifactURL() + UUID_PARAM
362 + artifact.getArtifactUUID() + ")" + System.lineSeparator() + "Error message is "
363 + downloadResult.getDistributionMessageResult() + System.lineSeparator());
367 this.sendASDCNotification(NotificationType.DOWNLOAD, artifact.getArtifactURL(), asdcConfig.getConsumerID(),
368 distributionId, DistributionStatusEnum.DOWNLOAD_OK, null, System.currentTimeMillis());
369 return downloadResult;
373 private void writeArtifactToFile(IArtifactInfo artifact, IDistributionClientDownloadResult resultArtifact) {
376 Paths.get(getMsoConfigPath(), "ASDC", artifact.getArtifactVersion(), artifact.getArtifactName())
377 .normalize().toString();
379 logger.info("Trying to write artifact UUID: {}, URL: {} to file: {}", artifact.getArtifactUUID(),
380 artifact.getArtifactURL(), filePath);
382 // make parent directory
383 File file = new File(filePath);
384 File fileParent = file.getParentFile();
385 if (!fileParent.exists()) {
389 byte[] payloadBytes = resultArtifact.getArtifactPayload();
391 try (FileOutputStream outFile = new FileOutputStream(filePath)) {
392 logger.info("{} {} {} {}", MessageEnum.ASDC_RECEIVE_SERVICE_NOTIF.toString(), "***WRITE FILE ARTIFACT NAME",
393 "ASDC", artifact.getArtifactName());
394 outFile.write(payloadBytes, 0, payloadBytes.length);
395 } catch (Exception e) {
396 logger.debug("Exception :", e);
397 logger.error("{} {} {} {} {} {} {}", MessageEnum.ASDC_ARTIFACT_DOWNLOAD_FAIL.toString(),
398 artifact.getArtifactName(), artifact.getArtifactURL(), artifact.getArtifactUUID(),
399 resultArtifact.getDistributionMessageResult(), ErrorCode.DataError.getValue(),
400 "ASDC write to file failed");
406 protected void sendDeployNotificationsForResource(ResourceStructure resourceStructure,
407 DistributionStatusEnum distribStatus, String errorReason) {
409 for (IArtifactInfo artifactInfo : resourceStructure.getResourceInstance().getArtifacts()) {
411 if ((DistributionStatusEnum.DEPLOY_OK.equals(distribStatus)
412 && !artifactInfo.getArtifactType().equalsIgnoreCase("OTHER")
413 && !resourceStructure.isAlreadyDeployed())
414 // This could be NULL if the artifact is a VF module artifact, this won't be present in the MAP
415 && resourceStructure.getArtifactsMapByUUID().get(artifactInfo.getArtifactUUID()) != null
416 && resourceStructure.getArtifactsMapByUUID().get(artifactInfo.getArtifactUUID())
417 .getDeployedInDb() == 0) {
418 this.sendASDCNotification(NotificationType.DEPLOY, artifactInfo.getArtifactURL(),
419 asdcConfig.getConsumerID(), resourceStructure.getNotification().getDistributionID(),
420 DistributionStatusEnum.DEPLOY_ERROR,
421 "The artifact has not been used by the modules defined in the resource",
422 System.currentTimeMillis());
424 this.sendASDCNotification(NotificationType.DEPLOY, artifactInfo.getArtifactURL(),
425 asdcConfig.getConsumerID(), resourceStructure.getNotification().getDistributionID(),
426 distribStatus, errorReason, System.currentTimeMillis());
431 protected void sendCsarDeployNotification(INotificationData iNotif, ResourceStructure resourceStructure,
432 ToscaResourceStructure toscaResourceStructure, DistributionStatusEnum statusEnum, String errorReason) {
434 IArtifactInfo csarArtifact = toscaResourceStructure.getToscaArtifact();
436 this.sendASDCNotification(NotificationType.DEPLOY, csarArtifact.getArtifactURL(), asdcConfig.getConsumerID(),
437 resourceStructure.getNotification().getDistributionID(), statusEnum, errorReason,
438 System.currentTimeMillis());
442 protected void deployResourceStructure(ResourceStructure resourceStructure,
443 ToscaResourceStructure toscaResourceStructure) throws ArtifactInstallerException {
445 logger.info("{} {} {} {}", MessageEnum.ASDC_START_DEPLOY_ARTIFACT.toString(),
446 resourceStructure.getResourceInstance().getResourceInstanceName(),
447 resourceStructure.getResourceInstance().getResourceUUID(), "ASDC");
449 resourceStructure.prepareInstall();
450 toscaInstaller.installTheResource(toscaResourceStructure, resourceStructure);
452 } catch (ArtifactInstallerException e) {
453 logger.info("{} {} {} {} {} {}", MessageEnum.ASDC_ARTIFACT_DOWNLOAD_FAIL.toString(),
454 resourceStructure.getResourceInstance().getResourceName(),
455 resourceStructure.getResourceInstance().getResourceUUID(),
456 String.valueOf(resourceStructure.getNumberOfResources()), "ASDC", "deployResourceStructure");
457 sendDeployNotificationsForResource(resourceStructure, DistributionStatusEnum.DEPLOY_ERROR, e.getMessage());
461 if (resourceStructure.isDeployedSuccessfully() || toscaResourceStructure.isDeployedSuccessfully()) {
462 logger.info("{} {} {} {} {} {}", MessageEnum.ASDC_ARTIFACT_DEPLOY_SUC.toString(),
463 resourceStructure.getResourceInstance().getResourceName(),
464 resourceStructure.getResourceInstance().getResourceUUID(),
465 String.valueOf(resourceStructure.getNumberOfResources()), "ASDC", "deployResourceStructure");
466 sendDeployNotificationsForResource(resourceStructure, DistributionStatusEnum.DEPLOY_OK, null);
472 private enum NotificationType {
476 protected void sendASDCNotification(NotificationType notificationType, String artifactURL, String consumerID,
477 String distributionID, DistributionStatusEnum status, String errorReason, long timestamp) {
479 String event = "Sending " + notificationType.name() + "(" + status.name() + ")"
480 + " notification to ASDC for artifact:" + artifactURL;
482 if (errorReason != null) {
483 event = event + "(" + errorReason + ")";
485 logger.info("{} {} {} {} {} {}", MessageEnum.ASDC_SEND_NOTIF_ASDC.toString(), notificationType.name(),
486 status.name(), artifactURL, "ASDC", "sendASDCNotification");
491 IDistributionStatusMessage message =
492 new DistributionStatusMessage(artifactURL, consumerID, distributionID, status, timestamp);
494 switch (notificationType) {
496 if (errorReason != null) {
497 this.distributionClient.sendDownloadStatus(message, errorReason);
499 this.distributionClient.sendDownloadStatus(message);
501 action = "sendDownloadStatus";
504 if (errorReason != null) {
505 this.distributionClient.sendDeploymentStatus(message, errorReason);
507 this.distributionClient.sendDeploymentStatus(message);
509 action = "sendDeploymentdStatus";
514 } catch (RuntimeException e) {
515 logger.warn("{} {} {} {} {}", MessageEnum.ASDC_SEND_NOTIF_ASDC_EXEC.toString(), "ASDC",
516 "sendASDCNotification", ErrorCode.SchemaError.getValue(), "RuntimeException - sendASDCNotification",
521 protected void sendFinalDistributionStatus(String distributionID, DistributionStatusEnum status,
522 String errorReason) {
524 logger.debug("Enter sendFinalDistributionStatus with DistributionID " + distributionID + " and Status of "
525 + status.name() + " and ErrorReason " + errorReason);
527 long subStarttime = System.currentTimeMillis();
530 IFinalDistrStatusMessage finalDistribution = new FinalDistributionStatusMessage(distributionID, status,
531 subStarttime, asdcConfig.getConsumerID());
533 if (errorReason == null) {
534 this.distributionClient.sendFinalDistrStatus(finalDistribution);
536 this.distributionClient.sendFinalDistrStatus(finalDistribution, errorReason);
540 } catch (RuntimeException e) {
541 logger.debug("Exception caught in sendFinalDistributionStatus {}", e.getMessage());
542 logger.warn("{} {} {} {} {}", MessageEnum.ASDC_SEND_NOTIF_ASDC_EXEC.toString(), "ASDC",
543 "sendASDCNotification", ErrorCode.SchemaError.getValue(), "RuntimeException - sendASDCNotification",
548 private Optional<String> getNotificationJson(INotificationData iNotif) {
549 ObjectMapper mapper = new ObjectMapper();
550 mapper.setSerializationInclusion(Include.NON_NULL);
551 mapper.setSerializationInclusion(Include.NON_EMPTY);
552 mapper.setSerializationInclusion(Include.NON_ABSENT);
553 mapper.enable(MapperFeature.USE_ANNOTATIONS);
554 mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
555 Optional<String> returnValue = Optional.empty();
557 returnValue = Optional.of(mapper.writeValueAsString(iNotif));
558 } catch (JsonProcessingException e) {
559 logger.error("Error converting incoming ASDC notification to JSON", e);
564 public void treatNotification(INotificationData iNotif) {
566 int noOfArtifacts = 0;
568 for (IResourceInstance resource : iNotif.getResources()) {
569 noOfArtifacts += resource.getArtifacts().size();
571 logger.info("{} {} {} {}", MessageEnum.ASDC_RECEIVE_CALLBACK_NOTIF.toString(), String.valueOf(noOfArtifacts),
572 iNotif.getServiceUUID(), "ASDC");
574 logger.debug(ASDCNotificationLogging.dumpASDCNotification(iNotif));
575 logger.info("{} {} {} {}", MessageEnum.ASDC_RECEIVE_SERVICE_NOTIF.toString(), iNotif.getServiceUUID(),
576 "ASDC", "treatNotification");
578 this.changeControllerStatus(ASDCControllerStatus.BUSY);
579 Optional<String> notificationMessage = getNotificationJson(iNotif);
580 toscaInstaller.processWatchdog(iNotif.getDistributionID(), iNotif.getServiceUUID(), notificationMessage,
581 asdcConfig.getConsumerID());
583 // Process only the Resource artifacts in MSO
584 this.processResourceNotification(iNotif);
586 // ********************************************************************************************************
587 // Start Watchdog loop and wait for all components to complete before reporting final status back.
588 // **If timer expires first then we will report a Distribution Error back to ASDC
589 // ********************************************************************************************************
590 long initialStartTime = System.currentTimeMillis();
591 boolean componentsComplete = false;
592 String distributionStatus = null;
593 String watchdogError = null;
594 String overallStatus = null;
595 int watchDogTimeout = asdcConfig.getWatchDogTimeout() * 1000;
596 boolean isDeploySuccess = false;
598 while (!componentsComplete && (System.currentTimeMillis() - initialStartTime) < watchDogTimeout) {
601 distributionStatus = wd.getOverallDistributionStatus(iNotif.getDistributionID());
602 Thread.sleep(watchDogTimeout / 10);
603 } catch (Exception e) {
604 logger.debug("Exception in Watchdog Loop {}", e.getMessage());
605 Thread.sleep(watchDogTimeout / 10);
608 if (distributionStatus != null
609 && !distributionStatus.equalsIgnoreCase(DistributionStatus.INCOMPLETE.name())) {
611 if (distributionStatus.equalsIgnoreCase(DistributionStatus.SUCCESS.name())) {
612 isDeploySuccess = true;
613 overallStatus = DistributionStatusEnum.DISTRIBUTION_COMPLETE_OK.name();
615 overallStatus = DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name();
617 componentsComplete = true;
621 if (!componentsComplete) {
622 logger.debug("Timeout of {} seconds was reached before all components reported status",
624 watchdogError = "Timeout occurred while waiting for all components to report status";
625 overallStatus = DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name();
628 if (distributionStatus == null) {
629 overallStatus = DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name();
630 logger.debug("DistributionStatus is null for DistributionId: {}", iNotif.getDistributionID());
634 wd.executePatchAAI(iNotif.getDistributionID(), iNotif.getServiceInvariantUUID(), overallStatus);
635 logger.debug("A&AI Updated succefully with Distribution Status!");
636 } catch (Exception e) {
637 logger.debug("Exception in Watchdog executePatchAAI(): {}", e.getMessage());
638 watchdogError = "Error calling A&AI " + e.getMessage();
639 if (e.getCause() != null) {
640 logger.debug("Exception caused by: {}", e.getCause().getMessage());
644 if (isDeploySuccess && watchdogError == null) {
645 sendFinalDistributionStatus(iNotif.getDistributionID(), DistributionStatusEnum.DISTRIBUTION_COMPLETE_OK,
647 WatchdogDistributionStatus wds = new WatchdogDistributionStatus(iNotif.getDistributionID());
648 wds.setDistributionIdStatus(DistributionStatusEnum.DISTRIBUTION_COMPLETE_OK.toString());
651 sendFinalDistributionStatus(iNotif.getDistributionID(),
652 DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR, watchdogError);
653 WatchdogDistributionStatus wds = new WatchdogDistributionStatus(iNotif.getDistributionID());
654 wds.setDistributionIdStatus(DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.toString());
659 } catch (ObjectOptimisticLockingFailureException e) {
662 "OptimisticLockingFailure for DistributionId: {} Another process "
663 + "has already altered this distribution, so not going to process it on this site.",
664 iNotif.getDistributionID());
665 logger.error("{} {} {} {} {} {}", MessageEnum.ASDC_GENERAL_EXCEPTION_ARG.toString(),
666 "Database concurrency exception: ", "ASDC", "treatNotification",
667 ErrorCode.BusinessProcesssError.getValue(), "RuntimeException in treatNotification", e);
669 } catch (Exception e) {
670 logger.error("", MessageEnum.ASDC_GENERAL_EXCEPTION_ARG.toString(),
671 "Unexpected exception caught during the notification processing", "ASDC", "treatNotification",
672 ErrorCode.SchemaError.getValue(), "RuntimeException in treatNotification", e);
675 wd.executePatchAAI(iNotif.getDistributionID(), iNotif.getServiceInvariantUUID(),
676 DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name());
677 logger.debug("A&AI Updated succefully with Distribution Status of {}",
678 DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.name());
679 } catch (Exception aaiException) {
680 logger.debug("Exception in executePatchAAI(): {}", aaiException);
681 if (aaiException.getCause() != null) {
682 logger.debug("Exception caused by: {}", aaiException.getCause().getMessage());
686 sendFinalDistributionStatus(iNotif.getDistributionID(), DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR,
689 WatchdogDistributionStatus wds = new WatchdogDistributionStatus(iNotif.getDistributionID());
690 wds.setDistributionIdStatus(DistributionStatusEnum.DISTRIBUTION_COMPLETE_ERROR.toString());
694 this.changeControllerStatus(ASDCControllerStatus.IDLE);
698 protected void processResourceNotification(INotificationData iNotif) {
699 // For each artifact, create a structure describing the VFModule in a ordered flat level
700 ResourceStructure resourceStructure = null;
701 String msoConfigPath = getMsoConfigPath();
702 boolean hasVFResource = false;
703 ToscaResourceStructure toscaResourceStructure = new ToscaResourceStructure(msoConfigPath);
704 DistributionStatusEnum deployStatus = DistributionStatusEnum.DEPLOY_OK;
705 String errorMessage = null;
706 boolean serviceDeployed = false;
709 this.processCsarServiceArtifacts(iNotif, toscaResourceStructure);
710 IArtifactInfo iArtifact = toscaResourceStructure.getToscaArtifact();
712 msoConfigPath + "/ASDC/" + iArtifact.getArtifactVersion() + "/" + iArtifact.getArtifactName();
713 File csarFile = new File(filePath);
716 if (isCsarAlreadyDeployed(iNotif, toscaResourceStructure)) {
720 for (IResourceInstance resource : iNotif.getResources()) {
722 String resourceType = resource.getResourceType();
725 logger.info("Processing Resource Type: {}, Model UUID: {}", resourceType, resource.getResourceUUID());
727 if ("VF".equals(resourceType) && resource.getArtifacts() != null
728 && !resource.getArtifacts().isEmpty()) {
729 resourceStructure = new VfResourceStructure(iNotif, resource);
730 } else if ("PNF".equals(resourceType)) {
731 resourceStructure = new PnfResourceStructure(iNotif, resource);
733 // There are cases where the Service has no VF resources, those are handled here
734 logger.info("No resources found for Service: {}", iNotif.getServiceUUID());
735 resourceStructure = new VfResourceStructure(iNotif, new ResourceInstance());
736 resourceStructure.setResourceType(ResourceType.OTHER);
741 if (!this.checkResourceAlreadyDeployed(resourceStructure, serviceDeployed)) {
743 logger.debug("Processing Resource Type: " + resourceType + " and Model UUID: "
744 + resourceStructure.getResourceInstance().getResourceUUID());
746 if ("VF".equals(resourceType) && resource.getArtifacts() != null
747 && !resource.getArtifacts().isEmpty()) {
748 hasVFResource = true;
749 for (IArtifactInfo artifact : resource.getArtifacts()) {
750 IDistributionClientDownloadResult resultArtifact =
751 this.downloadTheArtifact(artifact, iNotif.getDistributionID());
752 if (resultArtifact != null) {
754 if (ASDCConfiguration.VF_MODULES_METADATA.equals(artifact.getArtifactType())) {
755 logger.debug("VF_MODULE_ARTIFACT: "
756 + new String(resultArtifact.getArtifactPayload(), "UTF-8"));
757 logger.debug(ASDCNotificationLogging
758 .dumpVfModuleMetaDataList(((VfResourceStructure) resourceStructure)
759 .decodeVfModuleArtifact(resultArtifact.getArtifactPayload())));
761 if (!ASDCConfiguration.WORKFLOW.equals(artifact.getArtifactType())) {
762 resourceStructure.addArtifactToStructure(distributionClient, artifact,
765 writeArtifactToFile(artifact, resultArtifact);
767 "Adding workflow artifact to structure: " + artifact.getArtifactName());
768 resourceStructure.addWorkflowArtifactToStructure(artifact, resultArtifact);
773 // Deploy VF resource and artifacts
774 logger.debug("Preparing to deploy Service: {}", iNotif.getServiceUUID());
777 this.deployResourceStructure(resourceStructure, toscaResourceStructure);
778 serviceDeployed = true;
782 } catch (ArtifactInstallerException e) {
783 deployStatus = DistributionStatusEnum.DEPLOY_ERROR;
784 errorMessage = e.getMessage();
785 logger.error("Exception occurred", e);
789 if (!hasVFResource) {
791 logger.debug("No resources found for Service: " + iNotif.getServiceUUID());
793 logger.debug("Preparing to deploy Service: {}", iNotif.getServiceUUID());
795 this.deployResourceStructure(resourceStructure, toscaResourceStructure);
796 } catch (ArtifactInstallerException e) {
797 deployStatus = DistributionStatusEnum.DEPLOY_ERROR;
798 errorMessage = e.getMessage();
799 logger.error("Exception occurred", e);
803 this.sendCsarDeployNotification(iNotif, resourceStructure, toscaResourceStructure, deployStatus,
806 } catch (ASDCDownloadException | UnsupportedEncodingException e) {
807 logger.error("{} {} {} {} {} {}", MessageEnum.ASDC_GENERAL_EXCEPTION_ARG.toString(),
808 "Exception caught during Installation of artifact", "ASDC", "processResourceNotification",
809 ErrorCode.BusinessProcesssError.getValue(), "Exception in processResourceNotification", e);
813 private String getMsoConfigPath() {
814 String msoConfigPath = System.getProperty("mso.config.path");
815 if (msoConfigPath == null) {
816 logger.info("Unable to find the system property mso.config.path, use the default configuration");
817 msoConfigPath = asdcConfig.getPropertyOrNull("mso.config.defaultpath");
819 if (msoConfigPath == null) {
820 logger.info("Unable to find the property: {} from configuration.", "mso.config.defaultpath");
823 logger.info("MSO config path is: {}", msoConfigPath);
824 return msoConfigPath;
827 protected void processCsarServiceArtifacts(INotificationData iNotif,
828 ToscaResourceStructure toscaResourceStructure) {
830 List<IArtifactInfo> serviceArtifacts = iNotif.getServiceArtifacts();
832 for (IArtifactInfo artifact : serviceArtifacts) {
834 if (artifact.getArtifactType().equals(ASDCConfiguration.TOSCA_CSAR)) {
838 toscaResourceStructure.setToscaArtifact(artifact);
840 IDistributionClientDownloadResult resultArtifact =
841 this.downloadTheArtifact(artifact, iNotif.getDistributionID());
843 writeArtifactToFile(artifact, resultArtifact);
845 toscaResourceStructure.updateResourceStructure(artifact);
847 toscaResourceStructure.setServiceVersion(iNotif.getServiceVersion());
849 logger.debug(ASDCNotificationLogging.dumpCSARNotification(iNotif, toscaResourceStructure));
852 } catch (Exception e) {
853 logger.error("{} {} {} {} {} {}", MessageEnum.ASDC_GENERAL_EXCEPTION_ARG.toString(),
854 "Exception caught during processCsarServiceArtifacts", "ASDC",
855 "processCsarServiceArtifacts", ErrorCode.BusinessProcesssError.getValue(),
856 "Exception in processCsarServiceArtifacts", e);
858 } else if (artifact.getArtifactType().equals(ASDCConfiguration.WORKFLOW)) {
862 IDistributionClientDownloadResult resultArtifact =
863 this.downloadTheArtifact(artifact, iNotif.getDistributionID());
865 writeArtifactToFile(artifact, resultArtifact);
867 toscaResourceStructure.setToscaArtifact(artifact);
869 logger.debug(ASDCNotificationLogging.dumpASDCNotification(iNotif));
872 } catch (Exception e) {
873 logger.info("Whats the error {}", e.getMessage());
874 logger.error("{} {} {} {} {} {}", MessageEnum.ASDC_GENERAL_EXCEPTION_ARG.toString(),
875 "Exception caught during processCsarServiceArtifacts", "ASDC",
876 "processCsarServiceArtifacts", ErrorCode.BusinessProcesssError.getValue(),
877 "Exception in processCsarServiceArtifacts", e);
885 private static final String UNKNOWN = "Unknown";
888 * @return the address of the ASDC we are connected to.
890 public String getAddress() {
891 if (asdcConfig != null) {
892 return asdcConfig.getAsdcAddress();
898 * @return the environment name of the ASDC we are connected to.
900 public String getEnvironment() {
901 if (asdcConfig != null) {
902 return asdcConfig.getEnvironmentName();