From cc96f30a504aa32030eafefdba69d635869c7949 Mon Sep 17 00:00:00 2001 From: Alexis de Talhouët Date: Thu, 18 Apr 2019 16:27:20 -0400 Subject: Add support for Ansible packages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - rework how to provide packages - support proxy as parameters Change-Id: I1d10d921ead0837aa0f74b965cadf985424ceedc Issue-ID: CCCSDK-1215 Signed-off-by: Alexis de Talhouët --- .../remote_scripts/Definitions/artifact_types.json | 8 ++ .../remote_scripts/Definitions/data_types.json | 28 +++- .../remote_scripts/Definitions/node_types.json | 10 +- .../remote_scripts/Definitions/remote_scripts.json | 62 +++++++++ .../remote_scripts/Scripts/ansible/first.yaml | 22 ++++ .../artifact_type/artifact-script-ansible.json | 8 ++ .../starter-type/data_type/dt-system-packages.json | 26 ++++ .../component-remote-python-executor.json | 8 ++ .../proto-definition/proto/CommandExecutor.proto | 27 ++-- .../model-catalog/proto-definition/proto/README | 12 ++ .../executor/ComponentRemotePythonExecutor.kt | 14 +- .../executor/ComponentRemotePythonExecutorTest.kt | 2 - .../core/api/data/BlueprintRemoteProcessorData.kt | 11 +- .../execution/RemoteScriptExecutionService.kt | 20 ++- ms/command-executor/src/main/docker/start.sh | 10 ++ .../src/main/python/command_executor_handler.py | 79 +++++++++-- .../src/main/python/proto/CommandExecutor_pb2.py | 146 ++++++++++++--------- 17 files changed, 379 insertions(+), 114 deletions(-) create mode 100644 components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Scripts/ansible/first.yaml create mode 100644 components/model-catalog/definition-type/starter-type/artifact_type/artifact-script-ansible.json create mode 100644 components/model-catalog/definition-type/starter-type/data_type/dt-system-packages.json create mode 100644 components/model-catalog/proto-definition/proto/README diff --git a/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/artifact_types.json b/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/artifact_types.json index 445236354..a6a34ae8e 100644 --- a/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/artifact_types.json +++ b/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/artifact_types.json @@ -7,6 +7,14 @@ "file_ext": [ "py" ] + }, + "artifact-script-ansible": { + "description": "Ansible Script file", + "version": "1.0.0", + "file_ext": [ + "yaml" + ], + "derived_from": "tosca.artifacts.Implementation" } } } \ No newline at end of file diff --git a/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/data_types.json b/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/data_types.json index b22e30d00..df594ab9e 100644 --- a/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/data_types.json +++ b/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/data_types.json @@ -1,3 +1,29 @@ { - "data_types": {} + "data_types": { + "dt-system-packages": { + "description": "This represent System Package Data Type", + "version": "1.0.0", + "properties": { + "type": { + "required": true, + "type": "string", + "constraints": [ + { + "valid_values": [ + "ANSIBLE", "PYTHON" + ] + } + ] + }, + "package": { + "required": true, + "type": "list", + "entry_schema" : { + "type" : "string" + } + } + }, + "derived_from": "tosca.datatypes.Root" + } + } } \ No newline at end of file diff --git a/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/node_types.json b/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/node_types.json index cd63f0091..0ee00b3ba 100644 --- a/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/node_types.json +++ b/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/node_types.json @@ -33,7 +33,15 @@ "command": { "description": "Command to execute.", "required": true, - "type": "string" + "type" : "string" + }, + "packages": { + "description": "Packages to install based on type.", + "required": true, + "type" : "list", + "entry_schema" : { + "type" : "dt-system-packages" + } } } } diff --git a/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/remote_scripts.json b/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/remote_scripts.json index 464911478..80ef02f4f 100644 --- a/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/remote_scripts.json +++ b/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/remote_scripts.json @@ -51,6 +51,31 @@ } } } + }, + "execute-remote-ansible": { + "steps": { + "execute-script": { + "description": "Execute Remote Ansible Script", + "target": "execute-remote-ansible", + "activities": [ + { + "call_operation": "" + } + ] + } + }, + "inputs": {}, + "outputs": { + "logs": { + "type": "json", + "value": { + "get_attribute": [ + "execute-remote-ansible", + "execution-logs" + ] + } + } + } } }, "node_templates": { @@ -79,6 +104,43 @@ "file": "Scripts/python/SamplePython.py" } } + }, + "execute-remote-ansible": { + "type": "component-remote-python-executor", + "interfaces": { + "ComponentRemotePythonExecutor": { + "operations": { + "process": { + "implementation": { + "primary": "component-script" + }, + "inputs": { + "command": "ansible-playbook first.yaml", + "packages": [ + { + "type": "PYTHON", + "package": [ + "ansible" + ] + }, + { + "type": "ANSIBLE", + "package": [ + "juniper.junos" + ] + } + ] + } + } + } + } + }, + "artifacts": { + "component-script": { + "type": "artifact-script-ansible", + "file": "Scripts/ansible/first.yaml" + } + } } } } diff --git a/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Scripts/ansible/first.yaml b/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Scripts/ansible/first.yaml new file mode 100644 index 000000000..78d292e10 --- /dev/null +++ b/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Scripts/ansible/first.yaml @@ -0,0 +1,22 @@ +--- +- name: Get Device Facts + hosts: dc1 + roles: + - juniper.junos + connection: local + gather_facts: no + + tasks: + - name: Checking NETCONF connectivity + wait_for: + host: "{{ inventory_hostname }}" + port: 830 + timeout: 5 + + - name: Retrieving information from devices running Junos OS + juniper_junos_facts: + host: "{{ inventory_hostname }}" + + - name: Print version + debug: + var: junos.version \ No newline at end of file diff --git a/components/model-catalog/definition-type/starter-type/artifact_type/artifact-script-ansible.json b/components/model-catalog/definition-type/starter-type/artifact_type/artifact-script-ansible.json new file mode 100644 index 000000000..943186d13 --- /dev/null +++ b/components/model-catalog/definition-type/starter-type/artifact_type/artifact-script-ansible.json @@ -0,0 +1,8 @@ +{ + "description": "Ansible Script file", + "version": "1.0.0", + "file_ext": [ + "yaml" + ], + "derived_from": "tosca.artifacts.Implementation" +} \ No newline at end of file diff --git a/components/model-catalog/definition-type/starter-type/data_type/dt-system-packages.json b/components/model-catalog/definition-type/starter-type/data_type/dt-system-packages.json new file mode 100644 index 000000000..81bb030b4 --- /dev/null +++ b/components/model-catalog/definition-type/starter-type/data_type/dt-system-packages.json @@ -0,0 +1,26 @@ +{ + "description": "This represent System Package Data Type", + "version": "1.0.0", + "properties": { + "type": { + "required": true, + "type": "string", + "constraints": [ + { + "valid_values": [ + "ANSIBLE", + "PYTHON" + ] + } + ] + }, + "package": { + "required": true, + "type": "list", + "entry_schema": { + "type": "string" + } + } + }, + "derived_from": "tosca.datatypes.Root" +} \ No newline at end of file diff --git a/components/model-catalog/definition-type/starter-type/node_type/component-remote-python-executor.json b/components/model-catalog/definition-type/starter-type/node_type/component-remote-python-executor.json index 99a4dd8dc..3eaee761f 100644 --- a/components/model-catalog/definition-type/starter-type/node_type/component-remote-python-executor.json +++ b/components/model-catalog/definition-type/starter-type/node_type/component-remote-python-executor.json @@ -32,6 +32,14 @@ "description": "Command to execute.", "required": true, "type": "string" + }, + "packages": { + "description": "Packages to install based on type.", + "required": true, + "type" : "list", + "entry_schema" : { + "type" : "dt-system-packages" + } } } } diff --git a/components/model-catalog/proto-definition/proto/CommandExecutor.proto b/components/model-catalog/proto-definition/proto/CommandExecutor.proto index f488cc1b4..8f02b8aea 100644 --- a/components/model-catalog/proto-definition/proto/CommandExecutor.proto +++ b/components/model-catalog/proto-definition/proto/CommandExecutor.proto @@ -10,14 +10,13 @@ message ExecutionInput { string correlationId = 2; // Optional Blueprint Information used to identify CBA content information in shared file structure environment. Identifiers identifiers = 3; - ScriptType scriptType = 4; // Actual Command to Execute in Scripting Environment - string command = 5; - int32 timeOut = 6; + string command = 4; + int32 timeOut = 5; // Extra Dynamic Properties for Command processing in JSON format - google.protobuf.Struct properties = 7; + google.protobuf.Struct properties = 6; // Request Time Stamp - google.protobuf.Timestamp timestamp = 8; + google.protobuf.Timestamp timestamp = 7; } message PrepareEnvInput { @@ -25,11 +24,10 @@ message PrepareEnvInput { string requestId = 2; // Optional Id used to correlate multiple requests so that it can identify previous request information. string correlationId = 3; - ScriptType scriptType = 4; - repeated string packages = 5; - int32 timeOut = 6; - google.protobuf.Struct properties = 7; - google.protobuf.Timestamp timestamp = 8; + repeated Packages packages = 4; + int32 timeOut = 5; + google.protobuf.Struct properties = 6; + google.protobuf.Timestamp timestamp = 7; } message Identifiers { @@ -49,11 +47,14 @@ enum ResponseStatus { FAILURE = 1; } -enum ScriptType { +message Packages { + PackageType type = 1; + repeated string package = 2; +} + +enum PackageType { PYTHON = 0; ANSIBLE = 1; - KOTLIN = 2; - SH = 3; } service CommandExecutorService { diff --git a/components/model-catalog/proto-definition/proto/README b/components/model-catalog/proto-definition/proto/README new file mode 100644 index 000000000..47bbf3f34 --- /dev/null +++ b/components/model-catalog/proto-definition/proto/README @@ -0,0 +1,12 @@ +To create python bindings, + +Prerequisites: + https://developers.google.com/protocol-buffers/docs/downloads + https://github.com/dropbox/mypy-protobuf + + +Command: + protoc -I=. --python_out=. --mypy_out=. CommandExecutor.proto + + + diff --git a/ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutor.kt b/ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutor.kt index 6437cdf03..17d5fc76d 100644 --- a/ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutor.kt +++ b/ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutor.kt @@ -16,6 +16,8 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.python.executor +import com.fasterxml.jackson.databind.node.MissingNode +import com.fasterxml.jackson.databind.node.NullNode import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.* import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractComponentFunction import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ExecutionServiceConstant @@ -47,6 +49,7 @@ open class ComponentRemotePythonExecutor(private val remoteScriptExecutionServic const val INPUT_ENDPOINT_SELECTOR = "endpoint-selector" const val INPUT_DYNAMIC_PROPERTIES = "dynamic-properties" const val INPUT_COMMAND = "command" + const val INPUT_PACKAGES = "packages" } override suspend fun processNB(executionRequest: ExecutionServiceInput) { @@ -75,11 +78,12 @@ open class ComponentRemotePythonExecutor(private val remoteScriptExecutionServic val endPointSelector = getOperationInput(INPUT_ENDPOINT_SELECTOR) val dynamicProperties = getOperationInput(INPUT_DYNAMIC_PROPERTIES) val command = getOperationInput(INPUT_COMMAND).asText() + val packages = getOperationInput(INPUT_PACKAGES) // TODO("Python execution command and Resolve some expressions with dynamic properties") val scriptCommand = command.replace(pythonScript.name, pythonScript.absolutePath) - val dependencies = operationAssignment.implementation?.dependencies +// val dependencies = operationAssignment.implementation?.dependencies try { // Open GRPC Connection @@ -87,13 +91,12 @@ open class ComponentRemotePythonExecutor(private val remoteScriptExecutionServic var executionLogs = "" - // If dependencies are defined, then install in remote server - if (dependencies != null && dependencies.isNotEmpty()) { + // If packages are defined, then install in remote server + if (packages !is MissingNode && packages !is NullNode) { val prepareEnvInput = PrepareRemoteEnvInput(requestId = processId, remoteIdentifier = RemoteIdentifier(blueprintName = blueprintName, blueprintVersion = blueprintVersion), - remoteScriptType = RemoteScriptType.PYTHON, - packages = dependencies + packages = packages ) val prepareEnvOutput = remoteScriptExecutionService.prepareEnv(prepareEnvInput) executionLogs = prepareEnvOutput.response @@ -106,7 +109,6 @@ open class ComponentRemotePythonExecutor(private val remoteScriptExecutionServic val remoteExecutionInput = RemoteScriptExecutionInput( requestId = processId, remoteIdentifier = RemoteIdentifier(blueprintName = blueprintName, blueprintVersion = blueprintVersion), - remoteScriptType = RemoteScriptType.PYTHON, command = scriptCommand) val remoteExecutionOutput = remoteScriptExecutionService.executeCommand(remoteExecutionInput) executionLogs += remoteExecutionOutput.response diff --git a/ms/blueprintsprocessor/functions/python-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutorTest.kt b/ms/blueprintsprocessor/functions/python-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutorTest.kt index 7cd5d5cac..03616d5e4 100644 --- a/ms/blueprintsprocessor/functions/python-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutorTest.kt +++ b/ms/blueprintsprocessor/functions/python-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutorTest.kt @@ -68,7 +68,6 @@ class MockRemoteScriptExecutionService : RemoteScriptExecutionService { override suspend fun prepareEnv(prepareEnvInput: PrepareRemoteEnvInput): RemoteScriptExecutionOutput { assertEquals(prepareEnvInput.requestId, "123456-1000", "failed to match request id") - assertEquals(prepareEnvInput.remoteScriptType, RemoteScriptType.PYTHON, "failed to match script type") assertNotNull(prepareEnvInput.packages, "failed to get packages") val remoteScriptExecutionOutput = mockk() @@ -78,7 +77,6 @@ class MockRemoteScriptExecutionService : RemoteScriptExecutionService { override suspend fun executeCommand(remoteExecutionInput: RemoteScriptExecutionInput): RemoteScriptExecutionOutput { assertEquals(remoteExecutionInput.requestId, "123456-1000", "failed to match request id") - assertEquals(remoteExecutionInput.remoteScriptType, RemoteScriptType.PYTHON, "failed to match script type") val remoteScriptExecutionOutput = mockk() every { remoteScriptExecutionOutput.status } returns StatusType.SUCCESS diff --git a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/api/data/BlueprintRemoteProcessorData.kt b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/api/data/BlueprintRemoteProcessorData.kt index da952c034..83254cecc 100644 --- a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/api/data/BlueprintRemoteProcessorData.kt +++ b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/api/data/BlueprintRemoteProcessorData.kt @@ -19,10 +19,6 @@ package org.onap.ccsdk.cds.blueprintsprocessor.core.api.data import com.fasterxml.jackson.databind.JsonNode import java.util.* -enum class RemoteScriptType { - PYTHON, ANSIBLE, KOTLIN, SH -} - enum class StatusType { SUCCESS, FAILURE } @@ -34,7 +30,6 @@ data class RemoteIdentifier(var blueprintName: String, data class RemoteScriptExecutionInput(var requestId: String, var correlationId: String? = null, var remoteIdentifier: RemoteIdentifier? = null, - var remoteScriptType: RemoteScriptType, var command: String, var timeOut: Long = 30, var properties: MutableMap = hashMapOf() @@ -49,8 +44,6 @@ data class RemoteScriptExecutionOutput(var requestId: String, data class PrepareRemoteEnvInput(var requestId: String, var correlationId: String? = null, var remoteIdentifier: RemoteIdentifier? = null, - var remoteScriptType: RemoteScriptType, - var packages: MutableList?, + var packages: JsonNode, var timeOut: Long = 120, - var properties: MutableMap = hashMapOf() -) \ No newline at end of file + var properties: MutableMap = hashMapOf()) \ No newline at end of file diff --git a/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/RemoteScriptExecutionService.kt b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/RemoteScriptExecutionService.kt index 7db5f52a4..99d4f8c24 100644 --- a/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/RemoteScriptExecutionService.kt +++ b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/RemoteScriptExecutionService.kt @@ -49,7 +49,7 @@ class GrpcRemoteScriptExecutionService(private val bluePrintGrpcLibPropertyServi private val log = LoggerFactory.getLogger(GrpcRemoteScriptExecutionService::class.java)!! private var channel: ManagedChannel? = null - private lateinit var commandExecutorServiceGrpc: CommandExecutorServiceGrpc.CommandExecutorServiceFutureStub + private lateinit var commandExecutorServiceGrpc: CommandExecutorServiceGrpc.CommandExecutorServiceBlockingStub override suspend fun init(selector: String) { // Get the GRPC Client Service based on selector @@ -57,7 +57,7 @@ class GrpcRemoteScriptExecutionService(private val bluePrintGrpcLibPropertyServi // Get the GRPC Channel channel = grpcClientService.channel() // Create Non Blocking Stub - commandExecutorServiceGrpc = CommandExecutorServiceGrpc.newFutureStub(channel) + commandExecutorServiceGrpc = CommandExecutorServiceGrpc.newBlockingStub(channel) checkNotNull(commandExecutorServiceGrpc) { "failed to create command executor grpc client for selector($selector)" @@ -66,7 +66,7 @@ class GrpcRemoteScriptExecutionService(private val bluePrintGrpcLibPropertyServi override suspend fun prepareEnv(prepareEnvInput: PrepareRemoteEnvInput) : RemoteScriptExecutionOutput { - val grpResponse = commandExecutorServiceGrpc.prepareEnv(prepareEnvInput.asGrpcData()).get() + val grpResponse = commandExecutorServiceGrpc.prepareEnv(prepareEnvInput.asGrpcData()) checkNotNull(grpResponse.status) { "failed to get GRPC prepare env response status for requestId($prepareEnvInput.requestId)" @@ -81,7 +81,7 @@ class GrpcRemoteScriptExecutionService(private val bluePrintGrpcLibPropertyServi override suspend fun executeCommand(remoteExecutionInput: RemoteScriptExecutionInput) : RemoteScriptExecutionOutput { - val grpResponse = commandExecutorServiceGrpc.executeCommand(remoteExecutionInput.asGrpcData()).get() + val grpResponse = commandExecutorServiceGrpc.executeCommand(remoteExecutionInput.asGrpcData()) checkNotNull(grpResponse.status) { "failed to get GRPC response status for requestId($remoteExecutionInput.requestId)" @@ -101,13 +101,20 @@ class GrpcRemoteScriptExecutionService(private val bluePrintGrpcLibPropertyServi fun PrepareRemoteEnvInput.asGrpcData(): PrepareEnvInput { val correlationId = this.correlationId ?: this.requestId + val packageList = mutableListOf() + + this.packages.toList().forEach { + val pckage = Packages.newBuilder() + JsonFormat.parser().merge(it.toString(), pckage) + packageList.add(pckage.build()) + } + return PrepareEnvInput.newBuilder() .setIdentifiers(this.remoteIdentifier!!.asGrpcData()) .setRequestId(this.requestId) .setCorrelationId(correlationId) - .setScriptType(ScriptType.valueOf(this.remoteScriptType.name)) .setTimeOut(this.timeOut.toInt()) - .addAllPackages(this.packages) + .addAllPackages(packageList) .setProperties(this.properties.asGrpcData()) .build() } @@ -118,7 +125,6 @@ class GrpcRemoteScriptExecutionService(private val bluePrintGrpcLibPropertyServi .setRequestId(this.requestId) .setCorrelationId(correlationId) .setIdentifiers(this.remoteIdentifier!!.asGrpcData()) - .setScriptType(ScriptType.valueOf(this.remoteScriptType.name)) .setCommand(this.command) .setTimeOut(this.timeOut.toInt()) .setProperties(this.properties.asGrpcData()) diff --git a/ms/command-executor/src/main/docker/start.sh b/ms/command-executor/src/main/docker/start.sh index 659038418..38357a091 100755 --- a/ms/command-executor/src/main/docker/start.sh +++ b/ms/command-executor/src/main/docker/start.sh @@ -28,5 +28,15 @@ then export BASIC_AUTH="Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==" fi +if [ "${http_proxy}" ] +then + echo "Setting http_proxy: ${http_proxy}" +fi + +if [ "${https_proxy}" ] +then + echo "Setting https_proxy: ${https_proxy}" +fi + cd /opt/app/onap/python/ python server.py ${APP_PORT} ${BASIC_AUTH} \ No newline at end of file diff --git a/ms/command-executor/src/main/python/command_executor_handler.py b/ms/command-executor/src/main/python/command_executor_handler.py index 4ae575b0f..248e44308 100644 --- a/ms/command-executor/src/main/python/command_executor_handler.py +++ b/ms/command-executor/src/main/python/command_executor_handler.py @@ -13,32 +13,51 @@ # See the License for the specific language governing permissions and # limitations under the License. # +from builtins import Exception, open, dict +from subprocess import CalledProcessError, PIPE + import logging import os import subprocess import virtualenv import venv -from builtins import Exception, open, dict -from subprocess import CalledProcessError, PIPE - import utils +import proto.CommandExecutor_pb2 as CommandExecutor_pb2 -class CommandExecutorHandler: +class CommandExecutorHandler(): def __init__(self, request): + self.request = request self.logger = logging.getLogger(self.__class__.__name__) self.blueprint_id = utils.get_blueprint_id(request) self.venv_home = '/opt/app/onap/blueprints/deploy/' + self.blueprint_id + self.installed = self.venv_home + '/.installed' - def prepare_env(self, request, results): - self.create_venv() - if not self.activate_venv(): + def is_installed(self): + if os.path.exists(self.installed): + return True + else: return False - for package in request.packages: - if not self.install(package, results): + def prepare_env(self, request, results): + if not self.is_installed(): + self.create_venv() + if not self.activate_venv(): + return False + + f = open(self.installed, "w+") + if not self.install_packages(request, CommandExecutor_pb2.PYTHON, f, results): + return False + f.write("\r\n") + results.append("\n") + if not self.install_packages(request, CommandExecutor_pb2.ANSIBLE, f, results): return False + f.close() + else: + f = open(self.installed, "r") + results.append(f.read()) + f.close() # deactivate_venv(blueprint_id) return True @@ -57,16 +76,50 @@ class CommandExecutorHandler: # deactivate_venv(blueprint_id) return True - def install(self, package, results): - self.logger.info("{} - Install package({}) in Python Virtual Environment".format(self.blueprint_id, package)) + def install_packages(self, request, type, f, results): + for package in request.packages: + if package.type == type: + f.write("Installed %s packages:\r\n" % CommandExecutor_pb2.PackageType.Name(type)) + for python_package in package.package: + f.write(" %s\r\n" % python_package) + if package.type == CommandExecutor_pb2.PYTHON: + success = self.install_python_packages(python_package, results) + else: + success = self.install_ansible_packages(python_package, results) + if not success: + f.close() + os.remove(self.installed) + return False + return True + + def install_python_packages(self, package, results): + self.logger.info( + "{} - Install Python package({}) in Python Virtual Environment".format(self.blueprint_id, package)) command = ["pip", "install", package] env = dict(os.environ) - # fixme - parameterize - # env['https_proxy'] = "https://fastweb.int.bell.ca:8083" + env['https_proxy'] = os.environ['https_proxy'] + + try: + results.append(subprocess.run(command, check=True, stdout=PIPE, stderr=PIPE, env=env).stdout.decode()) + results.append("\n") + return True + except CalledProcessError as e: + results.append(e.stderr.decode()) + return False + + def install_ansible_packages(self, package, results): + self.logger.info( + "{} - Install Ansible Role package({}) in Python Virtual Environment".format(self.blueprint_id, package)) + command = ["ansible-galaxy", "install", package, "-p", "Scripts/ansible/roles"] + + env = dict(os.environ) + # ansible galaxy uses https_proxy environment variable, but requires it to be set with http proxy value. + env['https_proxy'] = os.environ['http_proxy'] try: results.append(subprocess.run(command, check=True, stdout=PIPE, stderr=PIPE, env=env).stdout.decode()) + results.append("\n") return True except CalledProcessError as e: results.append(e.stderr.decode()) diff --git a/ms/command-executor/src/main/python/proto/CommandExecutor_pb2.py b/ms/command-executor/src/main/python/proto/CommandExecutor_pb2.py index 637d37d87..76fc19d02 100644 --- a/ms/command-executor/src/main/python/proto/CommandExecutor_pb2.py +++ b/ms/command-executor/src/main/python/proto/CommandExecutor_pb2.py @@ -22,7 +22,7 @@ DESCRIPTOR = _descriptor.FileDescriptor( package='org.onap.ccsdk.cds.controllerblueprints.command.api', syntax='proto3', serialized_options=_b('P\001'), - serialized_pb=_b('\n\x15\x43ommandExecutor.proto\x12\x33org.onap.ccsdk.cds.controllerblueprints.command.api\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xe4\x02\n\x0e\x45xecutionInput\x12\x11\n\trequestId\x18\x01 \x01(\t\x12\x15\n\rcorrelationId\x18\x02 \x01(\t\x12U\n\x0bidentifiers\x18\x03 \x01(\x0b\x32@.org.onap.ccsdk.cds.controllerblueprints.command.api.Identifiers\x12S\n\nscriptType\x18\x04 \x01(\x0e\x32?.org.onap.ccsdk.cds.controllerblueprints.command.api.ScriptType\x12\x0f\n\x07\x63ommand\x18\x05 \x01(\t\x12\x0f\n\x07timeOut\x18\x06 \x01(\x05\x12+\n\nproperties\x18\x07 \x01(\x0b\x32\x17.google.protobuf.Struct\x12-\n\ttimestamp\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"\xe6\x02\n\x0fPrepareEnvInput\x12U\n\x0bidentifiers\x18\x01 \x01(\x0b\x32@.org.onap.ccsdk.cds.controllerblueprints.command.api.Identifiers\x12\x11\n\trequestId\x18\x02 \x01(\t\x12\x15\n\rcorrelationId\x18\x03 \x01(\t\x12S\n\nscriptType\x18\x04 \x01(\x0e\x32?.org.onap.ccsdk.cds.controllerblueprints.command.api.ScriptType\x12\x10\n\x08packages\x18\x05 \x03(\t\x12\x0f\n\x07timeOut\x18\x06 \x01(\x05\x12+\n\nproperties\x18\x07 \x01(\x0b\x32\x17.google.protobuf.Struct\x12-\n\ttimestamp\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\">\n\x0bIdentifiers\x12\x15\n\rblueprintName\x18\x01 \x01(\t\x12\x18\n\x10\x62lueprintVersion\x18\x02 \x01(\t\"\xba\x01\n\x0f\x45xecutionOutput\x12\x11\n\trequestId\x18\x01 \x01(\t\x12\x10\n\x08response\x18\x02 \x01(\t\x12S\n\x06status\x18\x03 \x01(\x0e\x32\x43.org.onap.ccsdk.cds.controllerblueprints.command.api.ResponseStatus\x12-\n\ttimestamp\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp**\n\x0eResponseStatus\x12\x0b\n\x07SUCCESS\x10\x00\x12\x0b\n\x07\x46\x41ILURE\x10\x01*9\n\nScriptType\x12\n\n\x06PYTHON\x10\x00\x12\x0b\n\x07\x41NSIBLE\x10\x01\x12\n\n\x06KOTLIN\x10\x02\x12\x06\n\x02SH\x10\x03\x32\xd1\x02\n\x16\x43ommandExecutorService\x12\x98\x01\n\nprepareEnv\x12\x44.org.onap.ccsdk.cds.controllerblueprints.command.api.PrepareEnvInput\x1a\x44.org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionOutput\x12\x9b\x01\n\x0e\x65xecuteCommand\x12\x43.org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionInput\x1a\x44.org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionOutputB\x02P\x01\x62\x06proto3') + serialized_pb=_b('\n\x15\x43ommandExecutor.proto\x12\x33org.onap.ccsdk.cds.controllerblueprints.command.api\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\x8f\x02\n\x0e\x45xecutionInput\x12\x11\n\trequestId\x18\x01 \x01(\t\x12\x15\n\rcorrelationId\x18\x02 \x01(\t\x12U\n\x0bidentifiers\x18\x03 \x01(\x0b\x32@.org.onap.ccsdk.cds.controllerblueprints.command.api.Identifiers\x12\x0f\n\x07\x63ommand\x18\x04 \x01(\t\x12\x0f\n\x07timeOut\x18\x05 \x01(\x05\x12+\n\nproperties\x18\x06 \x01(\x0b\x32\x17.google.protobuf.Struct\x12-\n\ttimestamp\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"\xd0\x02\n\x0fPrepareEnvInput\x12U\n\x0bidentifiers\x18\x01 \x01(\x0b\x32@.org.onap.ccsdk.cds.controllerblueprints.command.api.Identifiers\x12\x11\n\trequestId\x18\x02 \x01(\t\x12\x15\n\rcorrelationId\x18\x03 \x01(\t\x12O\n\x08packages\x18\x04 \x03(\x0b\x32=.org.onap.ccsdk.cds.controllerblueprints.command.api.Packages\x12\x0f\n\x07timeOut\x18\x05 \x01(\x05\x12+\n\nproperties\x18\x06 \x01(\x0b\x32\x17.google.protobuf.Struct\x12-\n\ttimestamp\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\">\n\x0bIdentifiers\x12\x15\n\rblueprintName\x18\x01 \x01(\t\x12\x18\n\x10\x62lueprintVersion\x18\x02 \x01(\t\"\xba\x01\n\x0f\x45xecutionOutput\x12\x11\n\trequestId\x18\x01 \x01(\t\x12\x10\n\x08response\x18\x02 \x01(\t\x12S\n\x06status\x18\x03 \x01(\x0e\x32\x43.org.onap.ccsdk.cds.controllerblueprints.command.api.ResponseStatus\x12-\n\ttimestamp\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"k\n\x08Packages\x12N\n\x04type\x18\x01 \x01(\x0e\x32@.org.onap.ccsdk.cds.controllerblueprints.command.api.PackageType\x12\x0f\n\x07package\x18\x02 \x03(\t**\n\x0eResponseStatus\x12\x0b\n\x07SUCCESS\x10\x00\x12\x0b\n\x07\x46\x41ILURE\x10\x01*&\n\x0bPackageType\x12\n\n\x06PYTHON\x10\x00\x12\x0b\n\x07\x41NSIBLE\x10\x01\x32\xd1\x02\n\x16\x43ommandExecutorService\x12\x98\x01\n\nprepareEnv\x12\x44.org.onap.ccsdk.cds.controllerblueprints.command.api.PrepareEnvInput\x1a\x44.org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionOutput\x12\x9b\x01\n\x0e\x65xecuteCommand\x12\x43.org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionInput\x1a\x44.org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionOutputB\x02P\x01\x62\x06proto3') , dependencies=[google_dot_protobuf_dot_struct__pb2.DESCRIPTOR,google_dot_protobuf_dot_timestamp__pb2.DESCRIPTOR,]) @@ -43,15 +43,15 @@ _RESPONSESTATUS = _descriptor.EnumDescriptor( ], containing_type=None, serialized_options=None, - serialized_start=1114, - serialized_end=1156, + serialized_start=1116, + serialized_end=1158, ) _sym_db.RegisterEnumDescriptor(_RESPONSESTATUS) ResponseStatus = enum_type_wrapper.EnumTypeWrapper(_RESPONSESTATUS) -_SCRIPTTYPE = _descriptor.EnumDescriptor( - name='ScriptType', - full_name='org.onap.ccsdk.cds.controllerblueprints.command.api.ScriptType', +_PACKAGETYPE = _descriptor.EnumDescriptor( + name='PackageType', + full_name='org.onap.ccsdk.cds.controllerblueprints.command.api.PackageType', filename=None, file=DESCRIPTOR, values=[ @@ -63,29 +63,19 @@ _SCRIPTTYPE = _descriptor.EnumDescriptor( name='ANSIBLE', index=1, number=1, serialized_options=None, type=None), - _descriptor.EnumValueDescriptor( - name='KOTLIN', index=2, number=2, - serialized_options=None, - type=None), - _descriptor.EnumValueDescriptor( - name='SH', index=3, number=3, - serialized_options=None, - type=None), ], containing_type=None, serialized_options=None, - serialized_start=1158, - serialized_end=1215, + serialized_start=1160, + serialized_end=1198, ) -_sym_db.RegisterEnumDescriptor(_SCRIPTTYPE) +_sym_db.RegisterEnumDescriptor(_PACKAGETYPE) -ScriptType = enum_type_wrapper.EnumTypeWrapper(_SCRIPTTYPE) +PackageType = enum_type_wrapper.EnumTypeWrapper(_PACKAGETYPE) SUCCESS = 0 FAILURE = 1 PYTHON = 0 ANSIBLE = 1 -KOTLIN = 2 -SH = 3 @@ -118,36 +108,29 @@ _EXECUTIONINPUT = _descriptor.Descriptor( is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='scriptType', full_name='org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionInput.scriptType', index=3, - number=4, type=14, cpp_type=8, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='command', full_name='org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionInput.command', index=4, - number=5, type=9, cpp_type=9, label=1, + name='command', full_name='org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionInput.command', index=3, + number=4, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='timeOut', full_name='org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionInput.timeOut', index=5, - number=6, type=5, cpp_type=1, label=1, + name='timeOut', full_name='org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionInput.timeOut', index=4, + number=5, type=5, cpp_type=1, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='properties', full_name='org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionInput.properties', index=6, - number=7, type=11, cpp_type=10, label=1, + name='properties', full_name='org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionInput.properties', index=5, + number=6, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='timestamp', full_name='org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionInput.timestamp', index=7, - number=8, type=11, cpp_type=10, label=1, + name='timestamp', full_name='org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionInput.timestamp', index=6, + number=7, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, @@ -165,7 +148,7 @@ _EXECUTIONINPUT = _descriptor.Descriptor( oneofs=[ ], serialized_start=142, - serialized_end=498, + serialized_end=413, ) @@ -198,36 +181,29 @@ _PREPAREENVINPUT = _descriptor.Descriptor( is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='scriptType', full_name='org.onap.ccsdk.cds.controllerblueprints.command.api.PrepareEnvInput.scriptType', index=3, - number=4, type=14, cpp_type=8, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='packages', full_name='org.onap.ccsdk.cds.controllerblueprints.command.api.PrepareEnvInput.packages', index=4, - number=5, type=9, cpp_type=9, label=3, + name='packages', full_name='org.onap.ccsdk.cds.controllerblueprints.command.api.PrepareEnvInput.packages', index=3, + number=4, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='timeOut', full_name='org.onap.ccsdk.cds.controllerblueprints.command.api.PrepareEnvInput.timeOut', index=5, - number=6, type=5, cpp_type=1, label=1, + name='timeOut', full_name='org.onap.ccsdk.cds.controllerblueprints.command.api.PrepareEnvInput.timeOut', index=4, + number=5, type=5, cpp_type=1, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='properties', full_name='org.onap.ccsdk.cds.controllerblueprints.command.api.PrepareEnvInput.properties', index=6, - number=7, type=11, cpp_type=10, label=1, + name='properties', full_name='org.onap.ccsdk.cds.controllerblueprints.command.api.PrepareEnvInput.properties', index=5, + number=6, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='timestamp', full_name='org.onap.ccsdk.cds.controllerblueprints.command.api.PrepareEnvInput.timestamp', index=7, - number=8, type=11, cpp_type=10, label=1, + name='timestamp', full_name='org.onap.ccsdk.cds.controllerblueprints.command.api.PrepareEnvInput.timestamp', index=6, + number=7, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, @@ -244,8 +220,8 @@ _PREPAREENVINPUT = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=501, - serialized_end=859, + serialized_start=416, + serialized_end=752, ) @@ -282,8 +258,8 @@ _IDENTIFIERS = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=861, - serialized_end=923, + serialized_start=754, + serialized_end=816, ) @@ -334,26 +310,65 @@ _EXECUTIONOUTPUT = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=926, - serialized_end=1112, + serialized_start=819, + serialized_end=1005, +) + + +_PACKAGES = _descriptor.Descriptor( + name='Packages', + full_name='org.onap.ccsdk.cds.controllerblueprints.command.api.Packages', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='type', full_name='org.onap.ccsdk.cds.controllerblueprints.command.api.Packages.type', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='package', full_name='org.onap.ccsdk.cds.controllerblueprints.command.api.Packages.package', index=1, + number=2, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1007, + serialized_end=1114, ) _EXECUTIONINPUT.fields_by_name['identifiers'].message_type = _IDENTIFIERS -_EXECUTIONINPUT.fields_by_name['scriptType'].enum_type = _SCRIPTTYPE _EXECUTIONINPUT.fields_by_name['properties'].message_type = google_dot_protobuf_dot_struct__pb2._STRUCT _EXECUTIONINPUT.fields_by_name['timestamp'].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP _PREPAREENVINPUT.fields_by_name['identifiers'].message_type = _IDENTIFIERS -_PREPAREENVINPUT.fields_by_name['scriptType'].enum_type = _SCRIPTTYPE +_PREPAREENVINPUT.fields_by_name['packages'].message_type = _PACKAGES _PREPAREENVINPUT.fields_by_name['properties'].message_type = google_dot_protobuf_dot_struct__pb2._STRUCT _PREPAREENVINPUT.fields_by_name['timestamp'].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP _EXECUTIONOUTPUT.fields_by_name['status'].enum_type = _RESPONSESTATUS _EXECUTIONOUTPUT.fields_by_name['timestamp'].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP +_PACKAGES.fields_by_name['type'].enum_type = _PACKAGETYPE DESCRIPTOR.message_types_by_name['ExecutionInput'] = _EXECUTIONINPUT DESCRIPTOR.message_types_by_name['PrepareEnvInput'] = _PREPAREENVINPUT DESCRIPTOR.message_types_by_name['Identifiers'] = _IDENTIFIERS DESCRIPTOR.message_types_by_name['ExecutionOutput'] = _EXECUTIONOUTPUT +DESCRIPTOR.message_types_by_name['Packages'] = _PACKAGES DESCRIPTOR.enum_types_by_name['ResponseStatus'] = _RESPONSESTATUS -DESCRIPTOR.enum_types_by_name['ScriptType'] = _SCRIPTTYPE +DESCRIPTOR.enum_types_by_name['PackageType'] = _PACKAGETYPE _sym_db.RegisterFileDescriptor(DESCRIPTOR) ExecutionInput = _reflection.GeneratedProtocolMessageType('ExecutionInput', (_message.Message,), dict( @@ -384,6 +399,13 @@ ExecutionOutput = _reflection.GeneratedProtocolMessageType('ExecutionOutput', (_ )) _sym_db.RegisterMessage(ExecutionOutput) +Packages = _reflection.GeneratedProtocolMessageType('Packages', (_message.Message,), dict( + DESCRIPTOR = _PACKAGES, + __module__ = 'CommandExecutor_pb2' + # @@protoc_insertion_point(class_scope:org.onap.ccsdk.cds.controllerblueprints.command.api.Packages) + )) +_sym_db.RegisterMessage(Packages) + DESCRIPTOR._options = None @@ -393,8 +415,8 @@ _COMMANDEXECUTORSERVICE = _descriptor.ServiceDescriptor( file=DESCRIPTOR, index=0, serialized_options=None, - serialized_start=1218, - serialized_end=1555, + serialized_start=1201, + serialized_end=1538, methods=[ _descriptor.MethodDescriptor( name='prepareEnv', -- cgit 1.2.3-korg