[vFW_CNF_CDS] Add workflow health-check and K8sHealthCheck.kt script
[demo.git] / heat / vFW_CNF_CDS / templates / cba / Scripts / kotlin / K8sHealthCheck.kt
1 /*
2  * Copyright (C) 2021 Samsung Electronics
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *     http://www.apache.org/licenses/LICENSE-2.0
7  * Unless required by applicable law or agreed to in writing, software
8  * distributed under the License is distributed on an "AS IS" BASIS,
9  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10  * See the License for the specific language governing permissions and
11  * limitations under the License
12  */
13 package org.onap.ccsdk.cds.blueprintsprocessor.services.execution.scripts
14
15 import com.fasterxml.jackson.databind.node.ObjectNode
16 import kotlinx.coroutines.Job
17 import kotlinx.coroutines.cancel
18 import kotlinx.coroutines.delay
19 import kotlinx.coroutines.joinAll
20 import kotlinx.coroutines.launch
21 import kotlinx.coroutines.runBlocking
22 import org.onap.ccsdk.cds.blueprintsprocessor.core.BlueprintPropertiesService
23 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
24 import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.K8sConnectionPluginConfiguration
25 import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.instance.K8sPluginInstanceApi
26 import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.instance.healthcheck.K8sRbInstanceHealthCheck
27 import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.instance.healthcheck.K8sRbInstanceHealthCheckSimple
28 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractScriptComponentFunction
29 import org.slf4j.LoggerFactory
30
31 open class K8sHealthCheck : AbstractScriptComponentFunction() {
32
33     private val log = LoggerFactory.getLogger(K8sHealthCheck::class.java)!!
34
35     override fun getName(): String {
36         return "K8sHealthCheck"
37     }
38
39     private fun initPluginApi(): K8sPluginInstanceApi {
40         val bluePrintPropertiesService: BlueprintPropertiesService = this.functionDependencyInstanceAsType("blueprintPropertiesService")!!
41         val k8sConfiguration = K8sConnectionPluginConfiguration(bluePrintPropertiesService)
42
43         return K8sPluginInstanceApi(k8sConfiguration)
44     }
45
46     override suspend fun processNB(executionRequest: ExecutionServiceInput) {
47         val instanceApi = initPluginApi()
48
49         log.info("Health check script execution - START")
50         val configValueSetup: ObjectNode = getDynamicProperties("config-deploy-setup") as ObjectNode
51         log.info("Config Value Setup: $configValueSetup")
52
53         val instanceHealthCheckList = startInstanceHealthCheck(configValueSetup, instanceApi)
54         val statuses = getStatuses(instanceHealthCheckList, instanceApi)
55         log.info("Health check script execution - END")
56     }
57
58     private fun startInstanceHealthCheck(configValueSetup: ObjectNode, instanceApi: K8sPluginInstanceApi): List<HealthCheckInstance> {
59         val healthCheckInstanceList = arrayListOf<HealthCheckInstance>()
60
61         configValueSetup.fields().forEach {
62             val instanceName = it.value.get("k8s-instance-id").asText()
63             val response: K8sRbInstanceHealthCheckSimple? = instanceApi.startInstanceHealthCheck(instanceName)
64             log.debug("K8sRbInstanceHealthCheckSimple response: $$response")
65             healthCheckInstanceList.add(HealthCheckInstance(instanceName, response?.id))
66         }
67         log.info("healthCheckInstanceList: $healthCheckInstanceList")
68
69         return healthCheckInstanceList
70     }
71
72     private fun getStatuses(instanceHealthCheckList: List<HealthCheckInstance>, instanceApi: K8sPluginInstanceApi): Map<String, String> {
73         val statuses = hashMapOf<String, String>()
74         runBlocking {
75             val jobs: List<Job> = instanceHealthCheckList.map {
76                 launch {
77                     log.info("Thread started: ${Thread.currentThread().name} for $it")
78                     // WAIT APPROX 5 MINUTES
79                     repeat(30) { _ ->
80                         val response: K8sRbInstanceHealthCheck = instanceApi.getInstanceHealthCheck(it.heatStackId, it.healthCheckInstance!!)!!
81                         log.debug("Response for $it: $response")
82                         val status = response.status!!
83                         if (!"RUNNING".equals(status, true)) {
84                             statuses[it.heatStackId] = status
85                             log.info("Poll status: $status for $it")
86                             instanceApi.deleteInstanceHealthCheck(it.heatStackId, it.healthCheckInstance)
87                             cancel()
88                         }
89                         delay(10_000L)
90                     }
91                     statuses[it.heatStackId] = "Timeout"
92                     log.warn("Send delete hc request")
93                     instanceApi.deleteInstanceHealthCheck(it.heatStackId, it.healthCheckInstance!!)
94                 }
95             }
96             jobs.joinAll()
97         }
98         log.info("Get statuses finished:")
99         log.info("$statuses")
100         return statuses
101     }
102
103     data class HealthCheckInstance(val heatStackId: String, val healthCheckInstance: String?) {
104         override fun toString(): String {
105             return "HealthCheckInstance(heatStackId='$heatStackId', healthCheckInstance='$healthCheckInstance')"
106         }
107     }
108
109     override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
110         log.info("Executing Recovery")
111         bluePrintRuntimeService.getBlueprintError().addError("${runtimeException.message}", getName())
112     }
113 }