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