2f91be86dfc520b38fbc28d204f65cff754a4fff
[so/adapters/so-cnf-adapter.git] /
1 package org.onap.so.adapters.cnf.service.healthcheck;
2
3 import com.google.common.util.concurrent.ThreadFactoryBuilder;
4 import org.onap.so.adapters.cnf.client.MulticloudClient;
5 import org.onap.so.adapters.cnf.model.CheckInstanceRequest;
6 import org.onap.so.adapters.cnf.model.InstanceRequest;
7 import org.onap.so.adapters.cnf.model.healthcheck.HealthCheckInstance;
8 import org.onap.so.adapters.cnf.model.healthcheck.HealthCheckInstanceResponse;
9 import org.onap.so.adapters.cnf.model.healthcheck.HealthCheckResponse;
10 import org.onap.so.adapters.cnf.model.healthcheck.K8sRbInstanceHealthCheck;
11 import org.onap.so.adapters.cnf.model.healthcheck.K8sRbInstanceHealthCheckSimple;
12 import org.onap.so.adapters.cnf.service.CnfAdapterService;
13 import org.onap.so.client.exception.BadResponseException;
14 import org.slf4j.Logger;
15 import org.slf4j.LoggerFactory;
16 import org.springframework.beans.factory.annotation.Autowired;
17 import org.springframework.stereotype.Service;
18
19 import java.util.ArrayList;
20 import java.util.List;
21 import java.util.concurrent.Callable;
22 import java.util.concurrent.ExecutorService;
23 import java.util.concurrent.ThreadFactory;
24 import java.util.stream.Collectors;
25
26 import static java.lang.Thread.sleep;
27 import static java.util.concurrent.Executors.newFixedThreadPool;
28
29 @Service
30 public class HealthCheckService {
31
32     private static final Logger log = LoggerFactory.getLogger(CnfAdapterService.class);
33
34     private final MulticloudClient instanceApi;
35
36     @Autowired
37     public HealthCheckService(MulticloudClient multicloudClient) {
38         this.instanceApi = multicloudClient;
39     }
40
41     public HealthCheckResponse healthCheck(CheckInstanceRequest healthCheckRequest) throws Exception {
42         log.info("Health check - START");
43         List<HealthCheckInstance> instanceHealthCheckList = startInstanceHealthCheck(healthCheckRequest);
44         HealthCheckResponse statuses = getStatuses(instanceHealthCheckList);
45         log.info("Health check - END");
46
47         return statuses;
48     }
49
50     private List<HealthCheckInstance> startInstanceHealthCheck(CheckInstanceRequest healthCheckRequest) throws Exception {
51         log.debug("startInstanceHealthCheck - START");
52         List<HealthCheckInstance> healthCheckInstanceList = new ArrayList<>();
53
54         for (InstanceRequest instance : healthCheckRequest.getInstances()) {
55             String instanceId = instance.getInstanceId();
56             K8sRbInstanceHealthCheckSimple response = instanceApi.startInstanceHealthCheck(instanceId);
57             log.info("K8sRbInstanceHealthCheckSimple: {}", response);
58             healthCheckInstanceList.add(new HealthCheckInstance(instanceId, response.getId()));
59         }
60
61         log.info("healthCheckInstanceList: {}", healthCheckInstanceList);
62         log.debug("startInstanceHealthCheck - END");
63         return healthCheckInstanceList;
64     }
65
66     private HealthCheckResponse getStatuses(List<HealthCheckInstance> instanceHealthCheckList) throws Exception {
67         log.debug("getStatuses - START");
68         List<HealthCheckThread> threads = instanceHealthCheckList.stream()
69                 .map(HealthCheckThread::new)
70                 .collect(Collectors.toList());
71
72         int processors = Runtime.getRuntime().availableProcessors();
73         ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("Health-check-thread-%d").build();
74         ExecutorService executorService = newFixedThreadPool(processors, threadFactory);
75         HealthCheckResponse response = new HealthCheckResponse();
76         List<HealthCheckInstanceResponse> healthCheckInstance = null;
77         healthCheckInstance = executorService.invokeAll(threads).stream()
78             .map(future -> {
79                 try {
80                     InstanceStatusTuple instanceStatusTuple = future.get();
81                     String instanceId = instanceStatusTuple.getInstanceId();
82                     String status = instanceStatusTuple.getStatus();
83                     String reason = null;
84                     return new HealthCheckInstanceResponse(instanceId, reason, status);
85                 } catch (Exception e) {
86                     throw new RuntimeException(e);
87                 }
88             })
89             .collect(Collectors.toList());
90         response.setInstanceResponse(healthCheckInstance);
91         log.info("Get statuses response: \n {}", response);
92         log.debug("getStatuses - END");
93         return response;
94     }
95
96     private class HealthCheckThread implements Callable<InstanceStatusTuple> {
97
98         private final HealthCheckInstance healthCheckInstance;
99
100         HealthCheckThread(HealthCheckInstance healthCheckInstance) {
101             this.healthCheckInstance = healthCheckInstance;
102         }
103
104         /**
105          * Approx 5 minutes thread
106          * If timeout method returns tuple with HeatStackId => Timeout
107          * @return InstanceStatusTuple
108          * @throws InterruptedException
109          * @throws BadResponseException
110          */
111         @Override
112         public InstanceStatusTuple call() throws InterruptedException, BadResponseException {
113             log.info("{} started for: {}", Thread.currentThread().getName(), healthCheckInstance);
114             for (int retry = 0; retry < 30; retry++) {
115                 K8sRbInstanceHealthCheck response = instanceApi.getInstanceHealthCheck(healthCheckInstance.getInstanceId(), healthCheckInstance.getHealthCheckInstance());
116                 log.debug("Response for instanceId={}: {}", healthCheckInstance, response);
117                 String status = response.getStatus();
118                 if (!"RUNNING".equals(status.toUpperCase())) {
119                     log.info("Poll status: {} for {}", status, healthCheckInstance);
120                     instanceApi.deleteInstanceHealthCheck(healthCheckInstance.getInstanceId(), healthCheckInstance.getHealthCheckInstance());
121                     return new InstanceStatusTuple(healthCheckInstance.getInstanceId(), status);
122                 }
123                 sleep(10_000L);
124             }
125             return new InstanceStatusTuple(healthCheckInstance.getInstanceId(), "Timeout");
126         }
127     }
128
129     private class InstanceStatusTuple {
130         private final String instanceId;
131         private final String status;
132
133         InstanceStatusTuple(String instanceId, String status) {
134             this.instanceId = instanceId;
135             this.status = status;
136         }
137
138         String getInstanceId() {
139             return instanceId;
140         }
141
142         String getStatus() {
143             return status;
144         }
145     }
146
147 }