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