cb14ebeebe781f1ad2903c422838049da411ce19
[sdc.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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=========================================================
19  */
20 package org.openecomp.sdc.be.components.distribution.engine;
21
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Optional;
26 import java.util.concurrent.atomic.AtomicBoolean;
27 import java.util.regex.Matcher;
28 import java.util.regex.Pattern;
29 import javax.annotation.PostConstruct;
30 import javax.annotation.PreDestroy;
31 import javax.annotation.Resource;
32 import org.apache.commons.collections.CollectionUtils;
33 import org.apache.commons.lang3.StringUtils;
34 import org.openecomp.sdc.be.components.validation.ServiceDistributionValidation;
35 import org.openecomp.sdc.be.config.BeEcompErrorManager;
36 import org.openecomp.sdc.be.config.ConfigurationManager;
37 import org.openecomp.sdc.be.config.DistributionEngineConfiguration;
38 import org.openecomp.sdc.be.dao.api.ActionStatus;
39 import org.openecomp.sdc.be.model.Service;
40 import org.openecomp.sdc.be.model.User;
41 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
42 import org.openecomp.sdc.be.resources.data.OperationalEnvironmentEntry;
43 import org.openecomp.sdc.common.log.wrappers.Logger;
44 import org.springframework.beans.factory.annotation.Autowired;
45 import org.springframework.stereotype.Component;
46
47 @Component("distributionEngine")
48 public class DistributionEngine implements IDistributionEngine {
49
50     private static final Logger logger = Logger.getLogger(DistributionEngine.class.getName());
51     private static final Pattern FQDN_PATTERN = Pattern.compile(
52         "^([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})*$",
53         Pattern.CASE_INSENSITIVE);
54     @Autowired
55     private EnvironmentsEngine environmentsEngine;
56     @Resource
57     private DistributionNotificationSender distributionNotificationSender;
58     @Resource
59     private ServiceDistributionArtifactsBuilder serviceDistributionArtifactsBuilder;
60     @Resource
61     private DistributionEngineClusterHealth distributionEngineClusterHealth;
62     @Resource
63     private ServiceDistributionValidation serviceDistributionValidation;
64     private Map<String, DistributionEngineInitTask> envNamePerInitTask = new HashMap<>();
65     private Map<String, DistributionEnginePollingTask> envNamePerPollingTask = new HashMap<>();
66     private Map<String, AtomicBoolean> envNamePerStatus = new HashMap<>();
67
68     @Override
69     public boolean isActive() {
70         if (envNamePerInitTask.isEmpty()) {
71             return false;
72         }
73         for (DistributionEngineInitTask task : envNamePerInitTask.values()) {
74             boolean active = task.isActive();
75             if (!active) {
76                 return false;
77             }
78         }
79         return true;
80     }
81
82     @PostConstruct
83     private void init() {
84         logger.trace("Enter init method of DistributionEngine");
85         DistributionEngineConfiguration distributionEngineConfiguration = ConfigurationManager.getConfigurationManager()
86             .getDistributionEngineConfiguration();
87         boolean startDistributionEngine = distributionEngineConfiguration.isStartDistributionEngine();
88         logger.debug("Distribution engine activation parameter is {}", startDistributionEngine);
89         if (!startDistributionEngine) {
90             logger.info("The distribution engine is disabled");
91             this.distributionEngineClusterHealth.setHealthCheckUebIsDisabled();
92             return;
93         }
94         boolean isValidConfig = validateConfiguration(distributionEngineConfiguration);
95         if (!isValidConfig) {
96             BeEcompErrorManager.getInstance()
97                 .logBeUebSystemError(DistributionEngineInitTask.INIT_DISTRIBUTION_ENGINE_FLOW, "validate distribution configuration in init phase");
98             this.distributionEngineClusterHealth.setHealthCheckUebConfigurationError();
99             return;
100         }
101         List<String> environments = distributionEngineConfiguration.getEnvironments();
102         for (String envName : environments) {
103             logger.debug("init task for environment {}", envName);
104             AtomicBoolean status = new AtomicBoolean(false);
105             envNamePerStatus.put(envName, status);
106             environmentsEngine.connectUebTopicForDistributionConfTopic(envName, status, envNamePerInitTask, envNamePerPollingTask);
107         }
108         logger.debug("init UEB health check");
109         distributionEngineClusterHealth.startHealthCheckTask(envNamePerStatus);
110         logger.trace("Exit init method of DistributionEngine");
111     }
112
113     @PreDestroy
114     public void shutdown() {
115         logger.info("distribution engine shutdown - start");
116         if (envNamePerInitTask != null) {
117             for (DistributionEngineInitTask task : envNamePerInitTask.values()) {
118                 task.destroy();
119             }
120         }
121         if (envNamePerPollingTask != null) {
122             for (DistributionEnginePollingTask task : envNamePerPollingTask.values()) {
123                 task.destroy();
124             }
125         }
126     }
127
128     /**
129      * validate mandatory configuration parameters received
130      *
131      * @param deConfiguration: distribution engine configuration
132      * @return boolean result: true of false
133      */
134     protected boolean validateConfiguration(DistributionEngineConfiguration deConfiguration) {
135         String methodName = "validateConfiguration";
136         boolean result = isValidServers(deConfiguration.getUebServers(), methodName, "uebServers");
137         result = isValidParam(deConfiguration.getEnvironments(), methodName, "environments") && result;
138         result = isValidParam(deConfiguration.getUebPublicKey(), methodName, "uebPublicKey") && result;
139         result = isValidParam(deConfiguration.getUebSecretKey(), methodName, "uebSecretKey") && result;
140         result = isValidParam(deConfiguration.getDistributionNotifTopicName(), methodName, "distributionNotifTopicName") && result;
141         result = isValidParam(deConfiguration.getDistributionStatusTopicName(), methodName, "distributionStatusTopicName") && result;
142         result = isValidObject(deConfiguration.getCreateTopic(), methodName, "createTopic") && result;
143         result = isValidObject(deConfiguration.getDistributionStatusTopic(), methodName, "distributionStatusTopic") && result;
144         result = isValidObject(deConfiguration.getInitMaxIntervalSec(), methodName, "initMaxIntervalSec") && result;
145         result = isValidObject(deConfiguration.getInitRetryIntervalSec(), methodName, "initRetryIntervalSec") && result;
146         result = isValidParam(deConfiguration.getDistributionStatusTopic().getConsumerId(), methodName, "consumerId") && result;
147         result = isValidParam(deConfiguration.getDistributionStatusTopic().getConsumerGroup(), methodName, "consumerGroup") && result;
148         result = isValidObject(deConfiguration.getDistributionStatusTopic().getFetchTimeSec(), methodName, "fetchTimeSec") && result;
149         result = isValidObject(deConfiguration.getDistributionStatusTopic().getPollingIntervalSec(), methodName, "pollingIntervalSec") && result;
150         return result;
151     }
152
153     private boolean isValidServers(List<String> uebServers, String methodName, String paramName) {
154         if (uebServers == null || uebServers.isEmpty()) {
155             BeEcompErrorManager.getInstance().logBeMissingConfigurationError(methodName, paramName);
156             return false;
157         }
158         if (uebServers.size() < 2) {
159             BeEcompErrorManager.getInstance().logBeConfigurationInvalidListSizeError(methodName, paramName, 2);
160             return false;
161         }
162         for (String serverFqdn : uebServers) {
163             if (!isValidFqdn(serverFqdn)) {
164                 BeEcompErrorManager.getInstance().logBeInvalidConfigurationError(methodName, paramName, serverFqdn);
165                 return false;
166             }
167         }
168         return true;
169     }
170
171     private boolean isValidFqdn(String serverFqdn) {
172         try {
173             Matcher matcher = FQDN_PATTERN.matcher(serverFqdn);
174             return matcher.matches();
175         } catch (Exception e) {
176             logger.debug("Failed to match value of address {}", serverFqdn, e);
177             return false;
178         }
179     }
180
181     private boolean isValidParam(String paramValue, String methodName, String paramName) {
182         if (StringUtils.isEmpty(paramValue)) {
183             BeEcompErrorManager.getInstance().logBeMissingConfigurationError(methodName, paramName);
184             return false;
185         }
186         return true;
187     }
188
189     private boolean isValidParam(List<String> paramValue, String methodName, String paramName) {
190         if (CollectionUtils.isEmpty(paramValue)) {
191             BeEcompErrorManager.getInstance().logBeMissingConfigurationError(methodName, paramName);
192             return false;
193         }
194         return true;
195     }
196
197     private boolean isValidObject(Object paramValue, String methodName, String paramName) {
198         if (paramValue == null) {
199             BeEcompErrorManager.getInstance().logBeMissingConfigurationError(methodName, paramName);
200             return false;
201         }
202         return true;
203     }
204
205     private String getEnvironmentErrorDescription(StorageOperationStatus status) {
206         switch (status) {
207             case DISTR_ENVIRONMENT_NOT_AVAILABLE:
208                 return "environment is unavailable";
209             case DISTR_ENVIRONMENT_NOT_FOUND:
210                 return "environment is not configured in our system";
211             case DISTR_ENVIRONMENT_SENT_IS_INVALID:
212                 return "environment name is invalid";
213             default:
214                 return "unkhown";
215         }
216     }
217
218     @Override
219     public StorageOperationStatus isEnvironmentAvailable(String envName) {
220         if (envName == null || envName.isEmpty()) {
221             return StorageOperationStatus.DISTR_ENVIRONMENT_SENT_IS_INVALID;
222         }
223         AtomicBoolean status = envNamePerStatus.get(envName);
224         if (status == null) {
225             return StorageOperationStatus.DISTR_ENVIRONMENT_NOT_FOUND;
226         }
227         if (!status.get()) {
228             return StorageOperationStatus.DISTR_ENVIRONMENT_NOT_AVAILABLE;
229         }
230         return StorageOperationStatus.OK;
231     }
232
233     @Override
234     public StorageOperationStatus isEnvironmentAvailable() {
235         String envName = ConfigurationManager.getConfigurationManager().getDistributionEngineConfiguration().getEnvironments().get(0);
236         return isEnvironmentAvailable(envName);
237     }
238
239     @Override
240     public void disableEnvironment(String envName) {
241         AtomicBoolean status = envNamePerStatus.get(envName);
242         status.set(false);
243     }
244
245     @Override
246     public ActionStatus notifyService(String distributionId, Service service, INotificationData notificationData, String envName, User modifier) {
247         return notifyService(distributionId, service, notificationData, envName, envName, modifier);
248     }
249
250     @Override
251     public ActionStatus notifyService(String distributionId, Service service, INotificationData notificationData, String envId, String envName,
252                                       User modifier) {
253         logger.debug(
254             "Received notify service request. distributionId = {}, serviceUuid = {} serviceUid = {}, envName = {}, userId = {}, modifierName {}",
255             distributionId, service.getUUID(), service.getUniqueId(), envName, service.getLastUpdaterUserId(), modifier);
256         String topicName = buildTopicName(envName);
257         ActionStatus notifyServiceStatus = Optional.ofNullable(environmentsEngine.getEnvironmentById(envId)).map(EnvironmentMessageBusData::new).map(
258             messageBusData -> distributionNotificationSender
259                 .sendNotification(topicName, distributionId, messageBusData, notificationData, service, modifier))
260             .orElse(ActionStatus.DISTRIBUTION_ENVIRONMENT_NOT_AVAILABLE);
261         logger.debug("Finish notifyService. status is {}", notifyServiceStatus);
262         return notifyServiceStatus;
263     }
264
265     private String buildTopicName(String envName) {
266         DistributionEngineConfiguration deConfiguration = ConfigurationManager.getConfigurationManager().getDistributionEngineConfiguration();
267         String distributionNotifTopicName = deConfiguration.getDistributionNotifTopicName();
268         return DistributionEngineInitTask.buildTopicName(distributionNotifTopicName, envName);
269     }
270
271     @Override
272     public StorageOperationStatus isReadyForDistribution(String envName) {
273         StorageOperationStatus status = isEnvironmentAvailable(envName);
274         if (status != StorageOperationStatus.OK) {
275             String envErrorDec = getEnvironmentErrorDescription(status);
276             BeEcompErrorManager.getInstance().logBeDistributionEngineSystemError(DistributionNotificationSender.DISTRIBUTION_NOTIFICATION_SENDING,
277                 "Environment name " + envName + " is not available. Reason : " + envErrorDec);
278         }
279         return status;
280     }
281
282     @Override
283     public OperationalEnvironmentEntry getEnvironmentById(String opEnvId) {
284         return environmentsEngine.getEnvironmentById(opEnvId);
285     }
286
287     @Override
288     public OperationalEnvironmentEntry getEnvironmentByDmaapUebAddress(List<String> dmaapUebAddress) {
289         return environmentsEngine.getEnvironmentByDmaapUebAddress(dmaapUebAddress);
290     }
291
292     @Override
293     public INotificationData buildServiceForDistribution(Service service, String distributionId, String workloadContext) {
294         INotificationData value = serviceDistributionArtifactsBuilder.buildResourceInstanceForDistribution(service, distributionId, workloadContext);
295         value = serviceDistributionArtifactsBuilder.buildServiceForDistribution(value, service);
296         return value;
297     }
298 }