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