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