2 * Copyright © 2019 IBM.
3 * Modifications Copyright © 2020 Bell Canada.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 package org.onap.ccsdk.cds.blueprintsprocessor.services.execution
20 import com.fasterxml.jackson.databind.JsonNode
21 import com.google.protobuf.Struct
22 import com.google.protobuf.Timestamp
23 import com.google.protobuf.util.JsonFormat
24 import io.grpc.ManagedChannel
25 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.PrepareRemoteEnvInput
26 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.RemoteIdentifier
27 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.RemoteScriptUploadBlueprintInput
28 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.RemoteScriptExecutionInput
29 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.RemoteScriptExecutionOutput
30 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.RemoteScriptUploadBlueprintOutput
31 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.StatusType
32 import org.onap.ccsdk.cds.blueprintsprocessor.grpc.service.BluePrintGrpcClientService
33 import org.onap.ccsdk.cds.blueprintsprocessor.grpc.service.BluePrintGrpcLibPropertyService
34 import org.onap.ccsdk.cds.controllerblueprints.command.api.CommandExecutorServiceGrpc
35 import org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionInput
36 import org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionOutput
37 import org.onap.ccsdk.cds.controllerblueprints.command.api.Identifiers
38 import org.onap.ccsdk.cds.controllerblueprints.command.api.Packages
39 import org.onap.ccsdk.cds.controllerblueprints.command.api.PrepareEnvInput
40 import org.onap.ccsdk.cds.controllerblueprints.command.api.UploadBlueprintInput
41 import org.onap.ccsdk.cds.controllerblueprints.command.api.UploadBlueprintOutput
42 import org.onap.ccsdk.cds.controllerblueprints.core.jsonAsJsonType
43 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
44 import org.slf4j.LoggerFactory
45 import org.springframework.beans.factory.config.ConfigurableBeanFactory
46 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
47 import org.springframework.context.annotation.Scope
48 import org.springframework.stereotype.Service
49 import java.util.concurrent.TimeUnit
51 interface RemoteScriptExecutionService {
53 suspend fun init(selector: Any)
54 suspend fun uploadBlueprint(uploadBpInput: RemoteScriptUploadBlueprintInput): RemoteScriptUploadBlueprintOutput
55 suspend fun prepareEnv(prepareEnvInput: PrepareRemoteEnvInput): RemoteScriptExecutionOutput
56 suspend fun executeCommand(remoteExecutionInput: RemoteScriptExecutionInput): RemoteScriptExecutionOutput
60 @Service(ExecutionServiceConstant.SERVICE_GRPC_REMOTE_SCRIPT_EXECUTION)
61 @ConditionalOnProperty(
62 prefix = "blueprintprocessor.remoteScriptCommand", name = arrayOf("enabled"),
63 havingValue = "true", matchIfMissing = false
65 @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
66 class GrpcRemoteScriptExecutionService(private val bluePrintGrpcLibPropertyService: BluePrintGrpcLibPropertyService) :
67 RemoteScriptExecutionService {
69 private val log = LoggerFactory.getLogger(GrpcRemoteScriptExecutionService::class.java)!!
71 private var channel: ManagedChannel? = null
72 private lateinit var commandExecutorServiceGrpc: CommandExecutorServiceGrpc.CommandExecutorServiceBlockingStub
74 override suspend fun init(selector: Any) {
75 // Get the GRPC Client Service based on selector
76 val grpcClientService: BluePrintGrpcClientService = if (selector is JsonNode) {
77 bluePrintGrpcLibPropertyService.blueprintGrpcClientService(selector)
79 bluePrintGrpcLibPropertyService.blueprintGrpcClientService(selector.toString())
82 // Get the GRPC Channel
83 channel = grpcClientService.channel()
84 // Create Non Blocking Stub
85 commandExecutorServiceGrpc = CommandExecutorServiceGrpc.newBlockingStub(channel)
87 checkNotNull(commandExecutorServiceGrpc) {
88 "failed to create command executor grpc client for selector($selector)"
92 override suspend fun uploadBlueprint(uploadBPInput: RemoteScriptUploadBlueprintInput): RemoteScriptUploadBlueprintOutput {
93 val logPart = "requestId(${uploadBPInput.requestId}) subRequestId(${uploadBPInput.subRequestId}) blueprintName(${uploadBPInput.remoteIdentifier?.blueprintName}) blueprintVersion(${uploadBPInput.remoteIdentifier?.blueprintVersion}) blueprintUUID(${uploadBPInput.remoteIdentifier?.blueprintUUID})"
94 val grpcResponse = commandExecutorServiceGrpc
95 .withDeadlineAfter(uploadBPInput.timeOut * 1000, TimeUnit.MILLISECONDS)
96 .uploadBlueprint(uploadBPInput.asGrpcData())
97 checkNotNull(grpcResponse.status) {
98 "failed to get GRPC upload CBA response status for $logPart"
100 val uploadBlueprinOutput = grpcResponse.asJavaData()
101 log.info("Received Upload CBA response status(${uploadBlueprinOutput.status}) for $logPart payload(${uploadBlueprinOutput.payload})")
102 return uploadBlueprinOutput
105 override suspend fun prepareEnv(prepareEnvInput: PrepareRemoteEnvInput): RemoteScriptExecutionOutput {
106 val grpResponse = commandExecutorServiceGrpc
107 .withDeadlineAfter(prepareEnvInput.timeOut * 1000, TimeUnit.MILLISECONDS)
108 .prepareEnv(prepareEnvInput.asGrpcData())
110 checkNotNull(grpResponse.status) {
111 "failed to get GRPC prepare env response status for requestId(${prepareEnvInput.requestId})"
114 val remoteScriptExecutionOutput = grpResponse.asJavaData()
115 log.debug("Received prepare env response from command server for requestId(${prepareEnvInput.requestId})")
117 return remoteScriptExecutionOutput
120 override suspend fun executeCommand(remoteExecutionInput: RemoteScriptExecutionInput): RemoteScriptExecutionOutput {
122 commandExecutorServiceGrpc
123 .withDeadlineAfter(remoteExecutionInput.timeOut * 1000, TimeUnit.MILLISECONDS)
124 .executeCommand(remoteExecutionInput.asGrpcData())
126 checkNotNull(grpResponse.status) {
127 "failed to get GRPC response status for requestId(${remoteExecutionInput.requestId})"
130 log.debug("Received response from command server for requestId(${remoteExecutionInput.requestId})")
131 return grpResponse.asJavaData()
134 override suspend fun close() {
135 channel?.shutdownNow()
138 fun RemoteScriptUploadBlueprintInput.asGrpcData(): UploadBlueprintInput {
139 val correlationId = this.correlationId ?: this.requestId
140 return UploadBlueprintInput.newBuilder()
141 .setIdentifiers(this.remoteIdentifier!!.asGrpcData())
142 .setRequestId(this.requestId)
143 .setSubRequestId(this.subRequestId)
144 .setOriginatorId(this.originatorId)
145 .setCorrelationId(correlationId)
146 .setTimestamp(Timestamp.getDefaultInstance())
147 .setBinData(this.binData)
148 .setArchiveType(this.archiveType)
149 .setTimeOut(this.timeOut.toInt())
153 fun PrepareRemoteEnvInput.asGrpcData(): PrepareEnvInput {
154 val correlationId = this.correlationId ?: this.requestId
156 val packageList = mutableListOf<Packages>()
158 this.packages.toList().forEach {
159 val pckage = Packages.newBuilder()
160 JsonFormat.parser().merge(it.toString(), pckage)
161 packageList.add(pckage.build())
164 return PrepareEnvInput.newBuilder()
165 .setIdentifiers(this.remoteIdentifier!!.asGrpcData())
166 .setRequestId(this.requestId)
167 .setSubRequestId(this.subRequestId)
168 .setOriginatorId(this.originatorId)
169 .setCorrelationId(correlationId)
170 .setTimeOut(this.timeOut.toInt())
171 .addAllPackages(packageList)
172 .setProperties(this.properties.asGrpcData())
176 fun RemoteScriptExecutionInput.asGrpcData(): ExecutionInput {
177 val correlationId = this.correlationId ?: this.requestId
178 return ExecutionInput.newBuilder()
179 .setRequestId(this.requestId)
180 .setSubRequestId(this.subRequestId)
181 .setOriginatorId(this.originatorId)
182 .setCorrelationId(correlationId)
183 .setIdentifiers(this.remoteIdentifier!!.asGrpcData())
184 .setCommand(this.command)
185 .setTimeOut(this.timeOut.toInt())
186 .setProperties(this.properties.asGrpcData())
187 .setTimestamp(Timestamp.getDefaultInstance())
191 fun RemoteIdentifier.asGrpcData(): Identifiers? {
192 return Identifiers.newBuilder()
193 .setBlueprintName(this.blueprintName)
194 .setBlueprintVersion(this.blueprintVersion)
195 .setBlueprintUUID(this.blueprintUUID)
199 fun Map<String, JsonNode>.asGrpcData(): Struct {
200 val struct = Struct.newBuilder()
201 JsonFormat.parser().merge(JacksonUtils.getJson(this), struct)
202 return struct.build()
205 fun ExecutionOutput.asJavaData(): RemoteScriptExecutionOutput {
206 return RemoteScriptExecutionOutput(
207 requestId = this.requestId,
208 response = this.responseList,
209 status = StatusType.valueOf(this.status.name),
210 payload = payload.jsonAsJsonType(),
215 fun UploadBlueprintOutput.asJavaData(): RemoteScriptUploadBlueprintOutput {
216 return RemoteScriptUploadBlueprintOutput(
217 requestId = this.requestId,
218 subRequestId = this.subRequestId,
219 status = StatusType.valueOf(this.status.name),
220 payload = payload.jsonAsJsonType()