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