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