2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.mso.asdc.client;
24 import java.io.IOException;
25 import java.io.UnsupportedEncodingException;
26 import org.openecomp.sdc.api.IDistributionClient;
27 import org.openecomp.sdc.api.consumer.IDistributionStatusMessage;
28 import org.openecomp.sdc.api.consumer.INotificationCallback;
29 import org.openecomp.sdc.api.notification.IArtifactInfo;
30 import org.openecomp.sdc.api.notification.INotificationData;
31 import org.openecomp.sdc.api.notification.IResourceInstance;
32 import org.openecomp.sdc.api.results.IDistributionClientDownloadResult;
33 import org.openecomp.sdc.api.results.IDistributionClientResult;
34 import org.openecomp.sdc.impl.DistributionClientFactory;
35 import org.openecomp.sdc.utils.DistributionActionResultEnum;
36 import org.openecomp.sdc.utils.DistributionStatusEnum;
37 import org.openecomp.mso.asdc.client.exceptions.ASDCControllerException;
38 import org.openecomp.mso.asdc.client.exceptions.ASDCDownloadException;
39 import org.openecomp.mso.asdc.client.exceptions.ASDCParametersException;
40 import org.openecomp.mso.asdc.client.exceptions.ArtifactInstallerException;
41 import org.openecomp.mso.asdc.installer.IVfResourceInstaller;
42 import org.openecomp.mso.asdc.installer.VfResourceStructure;
43 import org.openecomp.mso.asdc.installer.heat.VfResourceInstaller;
44 import org.openecomp.mso.asdc.util.ASDCNotificationLogging;
45 import org.openecomp.mso.logger.MessageEnum;
46 import org.openecomp.mso.logger.MsoAlarmLogger;
47 import org.openecomp.mso.logger.MsoLogger;
48 import org.openecomp.mso.utils.UUIDChecker;
50 public class ASDCController {
52 protected static final MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.ASDC);
54 protected static MsoAlarmLogger alarmLogger = new MsoAlarmLogger ();
56 protected boolean isAsdcClientAutoManaged = false;
58 protected String controllerName;
61 * Inner class for Notification callback
65 private final class ASDCNotificationCallBack implements INotificationCallback {
67 private ASDCController asdcController;
69 ASDCNotificationCallBack (ASDCController controller) {
70 asdcController = controller;
74 * This method can be called multiple times at the same moment.
75 * The controller must be thread safe !
78 public void activateCallback (INotificationData iNotif) {
79 long startTime = System.currentTimeMillis ();
80 UUIDChecker.generateUUID (LOGGER);
81 MsoLogger.setServiceName ("NotificationHandler");
82 MsoLogger.setLogContext (iNotif.getDistributionID (), iNotif.getServiceUUID ());
83 String event = "Receive a callback notification in ASDC, nb of resources: " + iNotif.getResources ().size ();
85 asdcController.treatNotification (iNotif);
86 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Completed the treatment of the notification");
90 // ***** Controller STATUS code
92 protected int nbOfNotificationsOngoing = 0;
94 public int getNbOfNotificationsOngoing () {
95 return nbOfNotificationsOngoing;
98 private ASDCControllerStatus controllerStatus = ASDCControllerStatus.STOPPED;
100 protected synchronized final void changeControllerStatus (ASDCControllerStatus newControllerStatus) {
101 switch (newControllerStatus) {
104 ++this.nbOfNotificationsOngoing;
105 this.controllerStatus = newControllerStatus;
109 if (this.nbOfNotificationsOngoing > 1) {
110 --this.nbOfNotificationsOngoing;
112 this.nbOfNotificationsOngoing = 0;
113 this.controllerStatus = newControllerStatus;
118 this.controllerStatus = newControllerStatus;
124 public synchronized final ASDCControllerStatus getControllerStatus () {
125 return this.controllerStatus;
128 // ***** END of Controller STATUS code
130 protected ASDCConfiguration asdcConfig;
131 private IDistributionClient distributionClient;
132 private IVfResourceInstaller resourceInstaller;
134 public ASDCController (String controllerConfigName) {
135 isAsdcClientAutoManaged = true;
136 this.controllerName = controllerConfigName;
137 this.resourceInstaller = new VfResourceInstaller();
140 public ASDCController (String controllerConfigName, IDistributionClient asdcClient, IVfResourceInstaller resourceinstaller) {
142 distributionClient = asdcClient;
143 this.resourceInstaller = resourceinstaller;
144 this.controllerName = controllerConfigName;
147 public ASDCController (String controllerConfigName,IDistributionClient asdcClient) {
148 distributionClient = asdcClient;
149 this.controllerName = controllerConfigName;
150 this.resourceInstaller = new VfResourceInstaller();
154 * This method refresh the ASDC Controller config and restart the client.
156 * @return true if config has been reloaded, false otherwise
157 * @throws ASDCControllerException If case of issue with the init or close called during the config reload
158 * @throws ASDCParametersException If there is an issue with the parameters
159 * @throws IOException In case of the key file could not be loaded properly
161 public boolean updateConfigIfNeeded () throws ASDCParametersException, ASDCControllerException, IOException {
162 LOGGER.debug ("Checking whether ASDC config must be reloaded");
165 if (this.asdcConfig != null && this.asdcConfig.hasASDCConfigChanged ()) {
166 LOGGER.debug ("ASDC Config must be reloaded");
168 this.asdcConfig.refreshASDCConfig ();
172 LOGGER.debug ("ASDC Config must NOT be reloaded");
175 } catch (ASDCParametersException ep) {
176 // Try to close it at least to make it consistent with the file specified
177 // We cannot let it run with a different config file, even if it's bad.
178 // This call could potentially throw a ASDCController exception if the controller is currently BUSY.
186 * This method initializes the ASDC Controller and the ASDC Client.
188 * @throws ASDCControllerException It throws an exception if the ASDC Client cannot be instantiated or if an init
189 * attempt is done when already initialized
190 * @throws ASDCParametersException If there is an issue with the parameters provided
191 * @throws IOException In case of issues when trying to load the key file
193 public void initASDC () throws ASDCControllerException, ASDCParametersException, IOException {
194 String event = "Initialize the ASDC Controller";
195 MsoLogger.setServiceName ("InitASDC");
196 LOGGER.debug (event);
197 if (this.getControllerStatus () != ASDCControllerStatus.STOPPED) {
198 String endEvent = "The controller is already initialized, call the closeASDC method first";
199 throw new ASDCControllerException (endEvent);
202 if (asdcConfig == null) {
203 asdcConfig = new ASDCConfiguration (this.controllerName);
206 // attempt to refresh during init as MsoProperties is may be pointing to an old file
207 // Be careful this is static in MsoProperties
208 asdcConfig.refreshASDCConfig ();
210 if (this.distributionClient == null) {
211 distributionClient = DistributionClientFactory.createDistributionClient ();
213 long initStartTime = System.currentTimeMillis ();
214 IDistributionClientResult result = this.distributionClient.init (asdcConfig,
215 new ASDCNotificationCallBack (this));
216 if (!result.getDistributionActionResult ().equals (DistributionActionResultEnum.SUCCESS)) {
217 String endEvent = "ASDC distribution client init failed with reason:"
218 + result.getDistributionMessageResult ();
219 LOGGER.recordMetricEvent (initStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.UnknownError, "Initialization of the ASDC Controller failed with reason:" + result.getDistributionMessageResult (), "ASDC", "init", null);
220 LOGGER.debug (endEvent);
223 this.changeControllerStatus (ASDCControllerStatus.STOPPED);
224 throw new ASDCControllerException ("Initialization of the ASDC Controller failed with reason: "
225 + result.getDistributionMessageResult ());
227 LOGGER.recordMetricEvent (initStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully initialize ASDC Controller", "ASDC", "init", null);
229 long clientstartStartTime = System.currentTimeMillis ();
230 result = this.distributionClient.start ();
231 if (!result.getDistributionActionResult ().equals (DistributionActionResultEnum.SUCCESS)) {
232 String endEvent = "ASDC distribution client start failed with reason:"
233 + result.getDistributionMessageResult ();
234 LOGGER.recordMetricEvent (clientstartStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.UnknownError, endEvent, "ASDC", "start", null);
235 LOGGER.debug (endEvent);
237 this.changeControllerStatus (ASDCControllerStatus.STOPPED);
238 throw new ASDCControllerException ("Startup of the ASDC Controller failed with reason: "
239 + result.getDistributionMessageResult ());
241 LOGGER.recordMetricEvent (clientstartStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully start ASDC distribution client", "ASDC", "start", null);
244 this.changeControllerStatus (ASDCControllerStatus.IDLE);
245 LOGGER.info (MessageEnum.ASDC_INIT_ASDC_CLIENT_SUC, "ASDC", "changeControllerStatus");
249 * This method closes the ASDC Controller and the ASDC Client.
251 * @throws ASDCControllerException It throws an exception if the ASDC Client cannot be closed because
252 * it's currently BUSY in processing notifications.
254 public void closeASDC () throws ASDCControllerException {
256 MsoLogger.setServiceName ("CloseController");
257 if (this.getControllerStatus () == ASDCControllerStatus.BUSY) {
258 throw new ASDCControllerException ("Cannot close the ASDC controller as it's currently in BUSY state");
260 if (this.distributionClient != null) {
261 this.distributionClient.stop ();
262 // If auto managed we can set it to Null, ASDCController controls it.
263 // In the other case the client of this class has specified it, so we can't reset it
264 if (isAsdcClientAutoManaged) {
265 // Next init will initialize it with a new ASDC Client
266 this.distributionClient = null;
270 this.changeControllerStatus (ASDCControllerStatus.STOPPED);
273 private boolean checkResourceAlreadyDeployed (VfResourceStructure vfResource) throws ArtifactInstallerException {
275 if (this.resourceInstaller.isResourceAlreadyDeployed (vfResource)) {
276 LOGGER.info (MessageEnum.ASDC_ARTIFACT_ALREADY_EXIST,
277 vfResource.getResourceInstance().getResourceInstanceName(),
278 vfResource.getResourceInstance().getResourceUUID(),
279 vfResource.getResourceInstance().getResourceName(), "", "");
281 this.sendDeployNotificationsForResource(vfResource,DistributionStatusEnum.ALREADY_DOWNLOADED,null);
282 this.sendDeployNotificationsForResource(vfResource,DistributionStatusEnum.ALREADY_DEPLOYED,null);
291 private final static String UUID_PARAM = "(UUID:";
293 private IDistributionClientDownloadResult downloadTheArtifact (IArtifactInfo artifact,
294 String distributionId) throws ASDCDownloadException {
296 LOGGER.debug ("Trying to download the artifact : " + artifact.getArtifactURL ()
298 + artifact.getArtifactUUID ()
300 IDistributionClientDownloadResult downloadResult;
304 downloadResult = distributionClient.download (artifact);
305 if (null == downloadResult) {
306 LOGGER.info (MessageEnum.ASDC_ARTIFACT_NULL, artifact.getArtifactUUID (), "", "");
307 return downloadResult;
309 } catch (RuntimeException e) {
310 LOGGER.debug ("Not able to download the artifact due to an exception: " + artifact.getArtifactURL ());
311 this.sendASDCNotification (NotificationType.DOWNLOAD,
312 artifact.getArtifactURL (),
313 asdcConfig.getConsumerID (),
315 DistributionStatusEnum.DOWNLOAD_ERROR,
317 System.currentTimeMillis ());
319 throw new ASDCDownloadException ("Exception caught when downloading the artifact", e);
322 if (DistributionActionResultEnum.SUCCESS.equals(downloadResult.getDistributionActionResult ())) {
324 LOGGER.info (MessageEnum.ASDC_ARTIFACT_DOWNLOAD_SUC,
325 artifact.getArtifactURL (),
326 artifact.getArtifactUUID (),
327 String.valueOf (downloadResult.getArtifactPayload ().length), "", "");
331 LOGGER.error (MessageEnum.ASDC_ARTIFACT_DOWNLOAD_FAIL,
332 artifact.getArtifactName (),
333 artifact.getArtifactURL (),
334 artifact.getArtifactUUID (),
335 downloadResult.getDistributionMessageResult (), "", "", MsoLogger.ErrorCode.DataError, "ASDC artifact download fail");
337 this.sendASDCNotification (NotificationType.DOWNLOAD,
338 artifact.getArtifactURL (),
339 asdcConfig.getConsumerID (),
341 DistributionStatusEnum.DOWNLOAD_ERROR,
342 downloadResult.getDistributionMessageResult (),
343 System.currentTimeMillis ());
345 throw new ASDCDownloadException ("Artifact " + artifact.getArtifactName ()
346 + " could not be downloaded from ASDC URL "
347 + artifact.getArtifactURL ()
349 + artifact.getArtifactUUID ()
351 + System.lineSeparator ()
352 + "Error message is "
353 + downloadResult.getDistributionMessageResult ()
354 + System.lineSeparator ());
358 this.sendASDCNotification (NotificationType.DOWNLOAD,
359 artifact.getArtifactURL (),
360 asdcConfig.getConsumerID (),
362 DistributionStatusEnum.DOWNLOAD_OK,
364 System.currentTimeMillis ());
365 return downloadResult;
370 private void sendDeployNotificationsForResource(VfResourceStructure vfResourceStructure,DistributionStatusEnum distribStatus, String errorReason) {
372 for (IArtifactInfo artifactInfo : vfResourceStructure.getResourceInstance().getArtifacts()) {
374 if (DistributionStatusEnum.DEPLOY_OK.equals(distribStatus)
375 // This could be NULL if the artifact is a VF module artifact, this won't be present in the MAP
376 && vfResourceStructure.getArtifactsMapByUUID().get(artifactInfo.getArtifactUUID()) != null
377 && vfResourceStructure.getArtifactsMapByUUID().get(artifactInfo.getArtifactUUID()).getDeployedInDb() == 0) {
378 this.sendASDCNotification (NotificationType.DEPLOY,
379 artifactInfo.getArtifactURL (),
380 asdcConfig.getConsumerID (),
381 vfResourceStructure.getNotification().getDistributionID(),
382 DistributionStatusEnum.DEPLOY_ERROR,
383 "The artifact has not been used by the modules defined in the resource",
384 System.currentTimeMillis ());
386 this.sendASDCNotification (NotificationType.DEPLOY,
387 artifactInfo.getArtifactURL (),
388 asdcConfig.getConsumerID (),
389 vfResourceStructure.getNotification().getDistributionID(),
392 System.currentTimeMillis ());
397 private void deployResourceStructure (VfResourceStructure vfResourceStructure) throws ArtifactInstallerException {
399 LOGGER.info (MessageEnum.ASDC_START_DEPLOY_ARTIFACT, vfResourceStructure.getResourceInstance().getResourceInstanceName(), vfResourceStructure.getResourceInstance().getResourceUUID(), "ASDC", "deployResourceStructure");
401 vfResourceStructure.createVfModuleStructures();
402 resourceInstaller.installTheResource (vfResourceStructure);
404 } catch (ArtifactInstallerException e) {
406 sendDeployNotificationsForResource(vfResourceStructure,DistributionStatusEnum.DEPLOY_ERROR,e.getMessage());
410 if (vfResourceStructure.isDeployedSuccessfully()) {
411 LOGGER.info (MessageEnum.ASDC_ARTIFACT_DEPLOY_SUC,
412 vfResourceStructure.getResourceInstance().getResourceName(),
413 vfResourceStructure.getResourceInstance().getResourceUUID(),
414 String.valueOf (vfResourceStructure.getVfModuleStructure().size()), "ASDC", "deployResourceStructure");
415 sendDeployNotificationsForResource(vfResourceStructure,DistributionStatusEnum.DEPLOY_OK ,null);
420 private enum NotificationType {
424 private void sendASDCNotification (NotificationType notificationType,
427 String distributionID,
428 DistributionStatusEnum status,
432 String event = "Sending " + notificationType.name ()
436 + " notification to ASDC for artifact:"
439 if (errorReason != null) {
440 event=event+"("+errorReason+")";
442 LOGGER.info (MessageEnum.ASDC_SEND_NOTIF_ASDC, notificationType.name (), status.name (), artifactURL, "ASDC", "sendASDCNotification");
443 LOGGER.debug (event);
445 long subStarttime = System.currentTimeMillis ();
448 IDistributionStatusMessage message = new DistributionStatusMessage (artifactURL,
454 switch (notificationType) {
456 if (errorReason != null) {
457 this.distributionClient.sendDownloadStatus (message, errorReason);
459 this.distributionClient.sendDownloadStatus (message);
461 action = "sendDownloadStatus";
464 if (errorReason != null) {
465 this.distributionClient.sendDeploymentStatus (message, errorReason);
467 this.distributionClient.sendDeploymentStatus (message);
469 action = "sendDeploymentdStatus";
474 } catch (RuntimeException e) {
475 // TODO: May be a list containing the unsent notification should be
477 LOGGER.warn (MessageEnum.ASDC_SEND_NOTIF_ASDC_EXEC, "ASDC", "sendASDCNotification", MsoLogger.ErrorCode.SchemaError, "RuntimeException - sendASDCNotification", e);
479 LOGGER.recordMetricEvent (subStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully sent notification to ASDC", "ASDC", action, null);
482 public void treatNotification (INotificationData iNotif) {
484 int noOfArtifacts = 0;
485 for (IResourceInstance resource : iNotif.getResources ()) {
486 noOfArtifacts += resource.getArtifacts ().size ();
488 LOGGER.info (MessageEnum.ASDC_RECEIVE_CALLBACK_NOTIF,
489 String.valueOf (noOfArtifacts),
490 iNotif.getServiceUUID (), "ASDC", "treatNotification");
493 LOGGER.debug(ASDCNotificationLogging.dumpASDCNotification(iNotif));
494 LOGGER.info(MessageEnum.ASDC_RECEIVE_SERVICE_NOTIF, iNotif.getServiceUUID(), "ASDC", "treatNotification");
495 this.changeControllerStatus(ASDCControllerStatus.BUSY);
496 // Process only the Resource artifacts in MSO
497 for (IResourceInstance resource : iNotif.getResources()) {
499 // We process only VNF resource on MSO Side
500 if ("VF".equals(resource.getResourceType())) {
501 this.processResourceNotification(iNotif,resource);
507 } catch (RuntimeException e) {
508 LOGGER.error (MessageEnum.ASDC_GENERAL_EXCEPTION_ARG,
509 "Unexpected exception caught during the notification processing", "ASDC", "treatNotification", MsoLogger.ErrorCode.SchemaError, "RuntimeException in treatNotification",
512 this.changeControllerStatus (ASDCControllerStatus.IDLE);
517 private void processResourceNotification (INotificationData iNotif,IResourceInstance resource) {
518 // For each artifact, create a structure describing the VFModule in a ordered flat level
519 VfResourceStructure vfResourceStructure = new VfResourceStructure(iNotif,resource);
522 if (!this.checkResourceAlreadyDeployed(vfResourceStructure)) {
523 for (IArtifactInfo artifact : resource.getArtifacts()) {
525 IDistributionClientDownloadResult resultArtifact = this.downloadTheArtifact(artifact,
526 iNotif.getDistributionID());
528 if (resultArtifact != null) {
529 if (ASDCConfiguration.VF_MODULES_METADATA.equals(artifact.getArtifactType())) {
530 LOGGER.debug("VF_MODULE_ARTIFACT: "+new String(resultArtifact.getArtifactPayload(),"UTF-8"));
531 LOGGER.debug(ASDCNotificationLogging.dumpVfModuleMetaDataList(distributionClient.decodeVfModuleArtifact(resultArtifact.getArtifactPayload())));
533 vfResourceStructure.addArtifactToStructure(distributionClient,artifact, resultArtifact);
539 this.deployResourceStructure(vfResourceStructure);
542 } catch (ArtifactInstallerException | ASDCDownloadException | UnsupportedEncodingException e) {
543 LOGGER.error(MessageEnum.ASDC_GENERAL_EXCEPTION_ARG,
544 "Exception caught during Installation of artifact", "ASDC", "processResourceNotification", MsoLogger.ErrorCode.BusinessProcesssError, "Exception in processResourceNotification", e);
548 private static final String UNKNOWN="Unknown";
551 * @return the address of the ASDC we are connected to.
553 public String getAddress () {
554 if (asdcConfig != null) {
555 return asdcConfig.getAsdcAddress ();
561 * @return the environment name of the ASDC we are connected to.
563 public String getEnvironment () {
564 if (asdcConfig != null) {
565 return asdcConfig.getEnvironmentName ();