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.sdc.be.components.distribution.engine;
23 import org.apache.commons.collections.CollectionUtils;
24 import org.apache.commons.lang3.StringUtils;
25 import org.openecomp.sdc.be.components.validation.ServiceDistributionValidation;
26 import org.openecomp.sdc.be.config.BeEcompErrorManager;
27 import org.openecomp.sdc.be.config.ConfigurationManager;
28 import org.openecomp.sdc.be.config.DistributionEngineConfiguration;
29 import org.openecomp.sdc.be.dao.api.ActionStatus;
30 import org.openecomp.sdc.be.model.Service;
31 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
32 import org.openecomp.sdc.be.resources.data.OperationalEnvironmentEntry;
33 import org.openecomp.sdc.common.util.YamlToObjectConverter;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36 import org.springframework.beans.factory.annotation.Autowired;
37 import org.springframework.stereotype.Component;
39 import javax.annotation.PostConstruct;
40 import javax.annotation.PreDestroy;
41 import javax.annotation.Resource;
43 import java.util.concurrent.atomic.AtomicBoolean;
44 import java.util.regex.Matcher;
45 import java.util.regex.Pattern;
47 @Component("distributionEngine")
48 public class DistributionEngine implements IDistributionEngine {
50 private static final Logger LOGGER = LoggerFactory.getLogger(DistributionEngine.class);
51 private static final Pattern FQDN_PATTERN = Pattern.compile("^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])(\\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]))*(:[0-9]{2,4})*$", Pattern.CASE_INSENSITIVE);
54 private EnvironmentsEngine environmentsEngine;
57 private DistributionNotificationSender distributionNotificationSender;
60 private ServiceDistributionArtifactsBuilder serviceDistributionArtifactsBuilder;
63 private DistributionEngineClusterHealth distributionEngineClusterHealth;
66 private ServiceDistributionValidation serviceDistributionValidation;
68 private Map<String, DistributionEngineInitTask> envNamePerInitTask = new HashMap<>();
69 private Map<String, DistributionEnginePollingTask> envNamePerPollingTask = new HashMap<>();
70 private Map<String, AtomicBoolean> envNamePerStatus = new HashMap<>();
73 * The main method for testing only
76 public static void main(String[] args) {
78 List<String> servers = new ArrayList<>();
79 String server = "uebsb91kcdc.it.att.com:3904";
84 YamlToObjectConverter converter = new YamlToObjectConverter();
85 DistributionEngineConfiguration distributionEngineConfiguration = converter.convert("src/test/resources/config/catalog-be/distribEngine1/distribution-engine-configuration.yaml", DistributionEngineConfiguration.class);
87 DistributionEngineInitTask distributionEngineInitTask = new DistributionEngineInitTask(2l, distributionEngineConfiguration, "PROD", new AtomicBoolean(false), null, null, null);
88 distributionEngineInitTask.startTask();
93 public boolean isActive() {
95 if (envNamePerInitTask.isEmpty()) {
99 for (DistributionEngineInitTask task : envNamePerInitTask.values()) {
100 boolean active = task.isActive();
109 private void init() {
111 LOGGER.trace("Enter init method of DistributionEngine");
113 DistributionEngineConfiguration distributionEngineConfiguration = ConfigurationManager.getConfigurationManager().getDistributionEngineConfiguration();
115 boolean startDistributionEngine = distributionEngineConfiguration.isStartDistributionEngine();
116 LOGGER.debug("Distribution engine activation parameter is {}", startDistributionEngine);
117 if (!startDistributionEngine) {
118 LOGGER.info("The disribution engine is disabled");
120 this.distributionEngineClusterHealth.setHealthCheckUebIsDisabled();
125 boolean isValidConfig = validateConfiguration(distributionEngineConfiguration);
127 if (!isValidConfig) {
128 BeEcompErrorManager.getInstance().logBeUebSystemError(DistributionEngineInitTask.INIT_DISTRIBUTION_ENGINE_FLOW, "validate distribution configuration in init phase");
130 this.distributionEngineClusterHealth.setHealthCheckUebConfigurationError();
134 List<String> environments = distributionEngineConfiguration.getEnvironments();
136 for (String envName : environments) {
137 LOGGER.debug("init task for environment {}", envName);
138 AtomicBoolean status = new AtomicBoolean(false);
139 envNamePerStatus.put(envName, status);
140 environmentsEngine.connectUebTopicForDistributionConfTopic(envName, status, envNamePerInitTask, envNamePerPollingTask);
143 LOGGER.debug("init UEB health check");
144 distributionEngineClusterHealth.startHealthCheckTask(envNamePerStatus);
146 LOGGER.trace("Exit init method of DistributionEngine");
151 public void shutdown() {
152 LOGGER.info("distribution engine shutdown - start");
153 if (envNamePerInitTask != null) {
154 for (DistributionEngineInitTask task : envNamePerInitTask.values()) {
158 if (envNamePerPollingTask != null) {
159 for (DistributionEnginePollingTask task : envNamePerPollingTask.values()) {
167 * validate mandatory configuration parameters received
169 * @param deConfiguration
172 protected boolean validateConfiguration(DistributionEngineConfiguration deConfiguration) {
174 String methodName = "validateConfiguration";
176 boolean result = true;
177 result = isValidServers(deConfiguration.getUebServers(), methodName, "uebServers") && result;
178 result = isValidParam(deConfiguration.getEnvironments(), methodName, "environments") && result;
179 result = isValidParam(deConfiguration.getUebPublicKey(), methodName, "uebPublicKey") && result;
180 result = isValidParam(deConfiguration.getUebSecretKey(), methodName, "uebSecretKey") && result;
181 result = isValidParam(deConfiguration.getDistributionNotifTopicName(), methodName, "distributionNotifTopicName") && result;
182 result = isValidParam(deConfiguration.getDistributionStatusTopicName(), methodName, "distributionStatusTopicName") && result;
183 result = isValidObject(deConfiguration.getCreateTopic(), methodName, "createTopic") && result;
184 result = isValidObject(deConfiguration.getDistributionStatusTopic(), methodName, "distributionStatusTopic") && result;
185 result = isValidObject(deConfiguration.getInitMaxIntervalSec(), methodName, "initMaxIntervalSec") && result;
186 result = isValidObject(deConfiguration.getInitRetryIntervalSec(), methodName, "initRetryIntervalSec") && result;
187 result = isValidParam(deConfiguration.getDistributionStatusTopic().getConsumerId(), methodName, "consumerId") && result;
188 result = isValidParam(deConfiguration.getDistributionStatusTopic().getConsumerGroup(), methodName, "consumerGroup") && result;
189 result = isValidObject(deConfiguration.getDistributionStatusTopic().getFetchTimeSec(), methodName, "fetchTimeSec") && result;
190 result = isValidObject(deConfiguration.getDistributionStatusTopic().getPollingIntervalSec(), methodName, "pollingIntervalSec") && result;
195 private boolean isValidServers(List<String> uebServers, String methodName, String paramName) {
197 if (uebServers == null || uebServers.isEmpty()) {
198 BeEcompErrorManager.getInstance().logBeMissingConfigurationError(methodName, paramName);
202 if (uebServers.size() < 2) {
203 BeEcompErrorManager.getInstance().logBeConfigurationInvalidListSizeError(methodName, paramName, 2);
207 for (String serverFqdn : uebServers) {
208 if (!isValidFqdn(serverFqdn)) {
209 BeEcompErrorManager.getInstance().logBeInvalidConfigurationError(methodName, paramName, serverFqdn);
217 private boolean isValidFqdn(String serverFqdn) {
220 Matcher matcher = FQDN_PATTERN.matcher(serverFqdn);
221 return matcher.matches();
223 } catch (Exception e) {
224 LOGGER.debug("Failed to match value of address {}", serverFqdn, e);
229 private boolean isValidParam(String paramValue, String methodName, String paramName) {
231 if (StringUtils.isEmpty(paramValue)) {
232 BeEcompErrorManager.getInstance().logBeMissingConfigurationError(methodName, paramName);
238 private boolean isValidParam(List<String> paramValue, String methodName, String paramName) {
240 if (CollectionUtils.isEmpty(paramValue)) {
241 BeEcompErrorManager.getInstance().logBeMissingConfigurationError(methodName, paramName);
247 private boolean isValidObject(Object paramValue, String methodName, String paramName) {
249 if (paramValue == null) {
250 BeEcompErrorManager.getInstance().logBeMissingConfigurationError(methodName, paramName);
257 private String getEnvironmentErrorDescription(StorageOperationStatus status) {
260 case DISTR_ENVIRONMENT_NOT_AVAILABLE:
261 return "environment is unavailable";
262 case DISTR_ENVIRONMENT_NOT_FOUND:
263 return "environment is not configured in our system";
264 case DISTR_ENVIRONMENT_SENT_IS_INVALID:
265 return "environment name is invalid";
272 public StorageOperationStatus isEnvironmentAvailable(String envName) {
274 if (envName == null || envName.isEmpty()) {
276 return StorageOperationStatus.DISTR_ENVIRONMENT_SENT_IS_INVALID;
279 AtomicBoolean status = envNamePerStatus.get(envName);
280 if (status == null) {
281 return StorageOperationStatus.DISTR_ENVIRONMENT_NOT_FOUND;
285 return StorageOperationStatus.DISTR_ENVIRONMENT_NOT_AVAILABLE;
287 return StorageOperationStatus.OK;
291 public StorageOperationStatus isEnvironmentAvailable() {
293 String envName = ConfigurationManager.getConfigurationManager().getDistributionEngineConfiguration().getEnvironments().get(0);
295 return isEnvironmentAvailable(envName);
299 public void disableEnvironment(String envName) {
300 AtomicBoolean status = envNamePerStatus.get(envName);
305 public ActionStatus notifyService(String distributionId, Service service, INotificationData notificationData, String envName, String userId, String modifierName) {
306 return notifyService(distributionId, service, notificationData, envName, envName, userId, modifierName);
310 public ActionStatus notifyService(String distributionId, Service service, INotificationData notificationData, String envId, String envName, String userId, String modifierName) {
311 LOGGER.debug("Received notify service request. distributionId = {}, serviceUuid = {} serviceUid = {}, envName = {}, userId = {}, modifierName {}", distributionId, service.getUUID(), service.getUniqueId(), envName, userId, modifierName);
312 String topicName = buildTopicName(envName);
313 ActionStatus notifyServiceStatus = Optional.ofNullable(environmentsEngine.getEnvironmentById(envId))
314 .map(EnvironmentMessageBusData::new)
315 .map(messageBusData -> distributionNotificationSender.sendNotification(topicName, distributionId, messageBusData, notificationData, service, userId, modifierName))
316 .orElse(ActionStatus.DISTRIBUTION_ENVIRONMENT_NOT_AVAILABLE);
317 LOGGER.debug("Finish notifyService. status is {}", notifyServiceStatus);
318 return notifyServiceStatus;
321 private String buildTopicName(String envName) {
322 DistributionEngineConfiguration deConfiguration = ConfigurationManager.getConfigurationManager().getDistributionEngineConfiguration();
323 String distributionNotifTopicName = deConfiguration.getDistributionNotifTopicName();
324 return DistributionEngineInitTask.buildTopicName(distributionNotifTopicName, envName);
328 public StorageOperationStatus isReadyForDistribution(Service service, String envName) {
329 StorageOperationStatus status = isEnvironmentAvailable(envName);
330 if (status != StorageOperationStatus.OK) {
331 String envErrorDec = getEnvironmentErrorDescription(status);
332 BeEcompErrorManager.getInstance().logBeDistributionEngineSystemError(DistributionNotificationSender.DISTRIBUTION_NOTIFICATION_SENDING, "Environment name " + envName + " is not available. Reason : " + envErrorDec);
336 return verifyServiceHasDeploymentArtifacts(service);
340 public StorageOperationStatus verifyServiceHasDeploymentArtifacts(Service service) {
341 if (!serviceDistributionArtifactsBuilder.verifyServiceContainsDeploymentArtifacts(service)) {
342 return StorageOperationStatus.DISTR_ARTIFACT_NOT_FOUND;
344 return StorageOperationStatus.OK;
348 public OperationalEnvironmentEntry getEnvironmentById(String opEnvId) {
349 return environmentsEngine.getEnvironmentById(opEnvId);
353 public INotificationData buildServiceForDistribution(Service service, String distributionId, String workloadContext) {
354 INotificationData value = serviceDistributionArtifactsBuilder.buildResourceInstanceForDistribution(service, distributionId, workloadContext);
355 value = serviceDistributionArtifactsBuilder.buildServiceForDistribution(value, service);