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
13 package org.onap.ccsdk.cds.blueprintsprocessor.services.execution.scripts
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
31 open class K8sHealthCheck : AbstractScriptComponentFunction() {
33 private val log = LoggerFactory.getLogger(K8sHealthCheck::class.java)!!
35 override fun getName(): String {
36 return "K8sHealthCheck"
39 private fun initPluginApi(): K8sPluginInstanceApi {
40 val bluePrintPropertiesService: BlueprintPropertiesService = this.functionDependencyInstanceAsType("blueprintPropertiesService")!!
41 val k8sConfiguration = K8sConnectionPluginConfiguration(bluePrintPropertiesService)
43 return K8sPluginInstanceApi(k8sConfiguration)
46 override suspend fun processNB(executionRequest: ExecutionServiceInput) {
47 val instanceApi = initPluginApi()
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")
53 val instanceHealthCheckList = startInstanceHealthCheck(configValueSetup, instanceApi)
54 val statuses = getStatuses(instanceHealthCheckList, instanceApi)
55 log.info("Health check script execution - END")
58 private fun startInstanceHealthCheck(configValueSetup: ObjectNode, instanceApi: K8sPluginInstanceApi): List<HealthCheckInstance> {
59 val healthCheckInstanceList = arrayListOf<HealthCheckInstance>()
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))
67 log.info("healthCheckInstanceList: $healthCheckInstanceList")
69 return healthCheckInstanceList
72 private fun getStatuses(instanceHealthCheckList: List<HealthCheckInstance>, instanceApi: K8sPluginInstanceApi): Map<String, String> {
73 val statuses = hashMapOf<String, String>()
75 val jobs: List<Job> = instanceHealthCheckList.map {
77 log.info("Thread started: ${Thread.currentThread().name} for $it")
78 // WAIT APPROX 5 MINUTES
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)
91 statuses[it.heatStackId] = "Timeout"
92 log.warn("Send delete hc request")
93 instanceApi.deleteInstanceHealthCheck(it.heatStackId, it.healthCheckInstance!!)
99 statuses?.forEach { it ->
100 if (it.value != "Succeeded") {
106 log.info("Healthcheck finished successfully")
108 log.info("Healthcheck finished with failure")
110 log.info("Detailed results: $statuses")
115 data class HealthCheckInstance(val heatStackId: String, val healthCheckInstance: String?) {
116 override fun toString(): String {
117 return "HealthCheckInstance(heatStackId='$heatStackId', healthCheckInstance='$healthCheckInstance')"
121 override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
122 log.info("Executing Recovery")
123 bluePrintRuntimeService.getBlueprintError().addError("${runtimeException.message}", getName())