From c90edac236dffb7c495e266dd04991de7e8f04b7 Mon Sep 17 00:00:00 2001 From: Alexis de Talhouët Date: Mon, 25 Mar 2019 13:04:18 -0400 Subject: Migrate ccsdk/apps to ccsdk/cds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue-ID: CCSDK-1177 Issue-ID: CCSDK-1178 Change-Id: I0c02702fbec52211ca367abbba72aebecee8cbaa Signed-off-by: Alexis de Talhouët --- .../netconf/executor/ComponentNetconfExecutor.kt | 75 ---- .../netconf/executor/JsonParserService.kt | 24 -- .../netconf/executor/NetconfComponentFunction.kt | 70 ---- .../functions/netconf/executor/NetconfDevice.kt | 31 -- .../functions/netconf/executor/api/DeviceInfo.kt | 43 --- .../netconf/executor/api/NetconfException.kt | 24 -- .../netconf/executor/api/NetconfMessage.kt | 74 ---- .../netconf/executor/api/NetconfRpcService.kt | 142 -------- .../netconf/executor/api/NetconfSession.kt | 86 ----- .../netconf/executor/api/NetconfSessionListener.kt | 21 -- .../executor/core/NetconfDeviceCommunicator.kt | 243 ------------- .../netconf/executor/core/NetconfRpcServiceImpl.kt | 220 ----------- .../netconf/executor/core/NetconfSessionImpl.kt | 287 --------------- .../netconf/executor/utils/NetconfConstant.kt | 90 ----- .../netconf/executor/utils/NetconfMessageUtils.kt | 404 --------------------- .../netconf/executor/ComponentNetconfExecutor.kt | 75 ++++ .../netconf/executor/JsonParserService.kt | 24 ++ .../netconf/executor/NetconfComponentFunction.kt | 70 ++++ .../functions/netconf/executor/NetconfDevice.kt | 31 ++ .../functions/netconf/executor/api/DeviceInfo.kt | 43 +++ .../netconf/executor/api/NetconfException.kt | 24 ++ .../netconf/executor/api/NetconfMessage.kt | 74 ++++ .../netconf/executor/api/NetconfRpcService.kt | 142 ++++++++ .../netconf/executor/api/NetconfSession.kt | 86 +++++ .../netconf/executor/api/NetconfSessionListener.kt | 21 ++ .../executor/core/NetconfDeviceCommunicator.kt | 243 +++++++++++++ .../netconf/executor/core/NetconfRpcServiceImpl.kt | 220 +++++++++++ .../netconf/executor/core/NetconfSessionImpl.kt | 287 +++++++++++++++ .../netconf/executor/utils/NetconfConstant.kt | 90 +++++ .../netconf/executor/utils/NetconfMessageUtils.kt | 404 +++++++++++++++++++++ .../executor/ComponentNetconfExecutorTest.kt | 79 ---- .../netconf/executor/NetconfSessionImplTest.kt | 111 ------ .../executor/core/NetconfRpcServiceImplTest.kt | 124 ------- .../executor/mocks/NetconfDeviceSimulator.kt | 62 ---- .../executor/mocks/NetconfSubsystemFactory.kt | 125 ------- .../netconf/executor/utils/RpcMessageUtilsTest.kt | 306 ---------------- .../executor/ComponentNetconfExecutorTest.kt | 79 ++++ .../netconf/executor/NetconfSessionImplTest.kt | 111 ++++++ .../executor/core/NetconfRpcServiceImplTest.kt | 124 +++++++ .../executor/mocks/NetconfDeviceSimulator.kt | 62 ++++ .../executor/mocks/NetconfSubsystemFactory.kt | 125 +++++++ .../netconf/executor/utils/RpcMessageUtilsTest.kt | 306 ++++++++++++++++ .../src/test/resources/logback-test.xml | 2 +- 43 files changed, 2642 insertions(+), 2642 deletions(-) delete mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/ComponentNetconfExecutor.kt delete mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/JsonParserService.kt delete mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/NetconfComponentFunction.kt delete mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/NetconfDevice.kt delete mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/api/DeviceInfo.kt delete mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/api/NetconfException.kt delete mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/api/NetconfMessage.kt delete mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/api/NetconfRpcService.kt delete mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/api/NetconfSession.kt delete mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/api/NetconfSessionListener.kt delete mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/core/NetconfDeviceCommunicator.kt delete mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/core/NetconfRpcServiceImpl.kt delete mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/core/NetconfSessionImpl.kt delete mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/utils/NetconfConstant.kt delete mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/utils/NetconfMessageUtils.kt create mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/ComponentNetconfExecutor.kt create mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/JsonParserService.kt create mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/NetconfComponentFunction.kt create mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/NetconfDevice.kt create mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/DeviceInfo.kt create mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/NetconfException.kt create mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/NetconfMessage.kt create mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/NetconfRpcService.kt create mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/NetconfSession.kt create mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/NetconfSessionListener.kt create mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfDeviceCommunicator.kt create mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfRpcServiceImpl.kt create mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfSessionImpl.kt create mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/utils/NetconfConstant.kt create mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/utils/NetconfMessageUtils.kt delete mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/ComponentNetconfExecutorTest.kt delete mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/NetconfSessionImplTest.kt delete mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/core/NetconfRpcServiceImplTest.kt delete mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/mocks/NetconfDeviceSimulator.kt delete mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/mocks/NetconfSubsystemFactory.kt delete mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/utils/RpcMessageUtilsTest.kt create mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/ComponentNetconfExecutorTest.kt create mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/NetconfSessionImplTest.kt create mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfRpcServiceImplTest.kt create mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/mocks/NetconfDeviceSimulator.kt create mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/mocks/NetconfSubsystemFactory.kt create mode 100644 ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/utils/RpcMessageUtilsTest.kt (limited to 'ms/blueprintsprocessor/functions/netconf-executor/src') diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/ComponentNetconfExecutor.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/ComponentNetconfExecutor.kt deleted file mode 100644 index c2ccdafd1..000000000 --- a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/ComponentNetconfExecutor.kt +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright © 2017-2018 AT&T Intellectual Property. - * - * Modifications Copyright © 2019 IBM, Bell Canada. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor - -import com.fasterxml.jackson.databind.node.ArrayNode -import org.onap.ccsdk.apps.blueprintsprocessor.core.api.data.ExecutionServiceInput -import org.onap.ccsdk.apps.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants -import org.onap.ccsdk.apps.blueprintsprocessor.services.execution.AbstractComponentFunction -import org.onap.ccsdk.apps.blueprintsprocessor.services.execution.ComponentFunctionScriptingService -import org.onap.ccsdk.apps.controllerblueprints.core.getAsString -import org.slf4j.LoggerFactory -import org.springframework.beans.factory.config.ConfigurableBeanFactory -import org.springframework.context.annotation.Scope -import org.springframework.stereotype.Component - -@Component("component-netconf-executor") -@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) -open class ComponentNetconfExecutor(private var componentFunctionScriptingService: ComponentFunctionScriptingService) - : AbstractComponentFunction() { - - private val log = LoggerFactory.getLogger(ComponentNetconfExecutor::class.java) - - companion object { - const val SCRIPT_TYPE = "script-type" - const val SCRIPT_CLASS_REFERENCE = "script-class-reference" - const val INSTANCE_DEPENDENCIES = "instance-dependencies" - } - - - lateinit var scriptComponent: NetconfComponentFunction - - override fun process(executionRequest: ExecutionServiceInput) { - - val scriptType = operationInputs.getAsString(SCRIPT_TYPE) - val scriptClassReference = operationInputs.getAsString(SCRIPT_CLASS_REFERENCE) - val instanceDependenciesNode = operationInputs.get(INSTANCE_DEPENDENCIES) as? ArrayNode - - val scriptDependencies: MutableList = arrayListOf() - scriptDependencies.add(ResourceResolutionConstants.SERVICE_RESOURCE_RESOLUTION) - - instanceDependenciesNode?.forEach { instanceName -> - scriptDependencies.add(instanceName.textValue()) - } - - scriptComponent = componentFunctionScriptingService.scriptInstance(this, scriptType, - scriptClassReference, scriptDependencies) - - - checkNotNull(scriptComponent) { "failed to get netconf script component" } - - scriptComponent.process(executionServiceInput) - } - - override fun recover(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) { - scriptComponent.recover(runtimeException, executionRequest) - } - - -} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/JsonParserService.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/JsonParserService.kt deleted file mode 100644 index 111736633..000000000 --- a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/JsonParserService.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright © 2017-2018 AT&T Intellectual Property. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor - -import org.springframework.stereotype.Service - -@Service("json-parser-service") -class JsonParserService { - -} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/NetconfComponentFunction.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/NetconfComponentFunction.kt deleted file mode 100644 index fe8ba54dd..000000000 --- a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/NetconfComponentFunction.kt +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright © 2018-2019 IBM, Bell Canada. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor - -import com.fasterxml.jackson.databind.JsonNode -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.api.DeviceInfo -import org.onap.ccsdk.apps.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants -import org.onap.ccsdk.apps.blueprintsprocessor.functions.resource.resolution.ResourceResolutionService -import org.onap.ccsdk.apps.blueprintsprocessor.services.execution.AbstractScriptComponentFunction -import org.onap.ccsdk.apps.controllerblueprints.core.utils.JacksonUtils - -abstract class NetconfComponentFunction : AbstractScriptComponentFunction() { - - open fun resourceResolutionService(): ResourceResolutionService = - functionDependencyInstanceAsType(ResourceResolutionConstants.SERVICE_RESOURCE_RESOLUTION) - - // Called from python script - fun initializeNetconfConnection(requirementName: String): NetconfDevice { - val deviceInfo = deviceProperties(requirementName) - return NetconfDevice(deviceInfo) - } - - fun generateMessage(artifactName: String): String { - return bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactName) - } - - fun resolveFromDatabase(resolutionKey: String, artifactName: String): String { - return resourceResolutionService().resolveFromDatabase(bluePrintRuntimeService, artifactName, resolutionKey) - } - - fun resolveAndGenerateMessage(artifactMapping: String, artifactTemplate: String): String { - return resourceResolutionService().resolveResources(bluePrintRuntimeService, nodeTemplateName, - artifactMapping, artifactTemplate) - } - - fun resolveAndGenerateMessage(artifactPrefix: String): String { - return resourceResolutionService().resolveResources(bluePrintRuntimeService, nodeTemplateName, - artifactPrefix, mapOf()) - } - - private fun deviceProperties(requirementName: String): DeviceInfo { - - val blueprintContext = bluePrintRuntimeService.bluePrintContext() - - val requirement = blueprintContext.nodeTemplateRequirement(nodeTemplateName, requirementName) - - val capabilityProperties = bluePrintRuntimeService.resolveNodeTemplateCapabilityProperties(requirement - .node!!, requirement.capability!!) - - return deviceProperties(capabilityProperties) - } - - private fun deviceProperties(capabilityProperty: MutableMap): DeviceInfo { - return JacksonUtils.getInstanceFromMap(capabilityProperty, DeviceInfo::class.java) - } -} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/NetconfDevice.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/NetconfDevice.kt deleted file mode 100644 index 1c07c5e6c..000000000 --- a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/NetconfDevice.kt +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2019 Bell Canada. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor - -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.api.DeviceInfo -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.api.NetconfSession -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.core.NetconfRpcServiceImpl -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.core.NetconfSessionImpl - -data class NetconfDevice(val deviceInfo: DeviceInfo) { - val netconfRpcService = NetconfRpcServiceImpl(deviceInfo) - val netconfSession: NetconfSession - - init { - netconfSession = NetconfSessionImpl(deviceInfo, netconfRpcService) - netconfRpcService.setNetconfSession(netconfSession) - } -} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/api/DeviceInfo.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/api/DeviceInfo.kt deleted file mode 100644 index 466e6b5ed..000000000 --- a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/api/DeviceInfo.kt +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright © 2017-2018 AT&T Intellectual Property. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.api - -import com.fasterxml.jackson.annotation.JsonIgnore -import com.fasterxml.jackson.annotation.JsonProperty - -class DeviceInfo { - @get:JsonProperty("login-account") - var username: String? = null - @get:JsonProperty("login-key") - var password: String? = null - @get:JsonProperty("target-ip-address") - var ipAddress: String? = null - @get:JsonProperty("port-number") - var port: Int = 0 - @get:JsonProperty("connection-time-out") - var connectTimeout: Long = 5 - @get:JsonIgnore - var source: String? = null - @get:JsonIgnore - var replyTimeout: Int = 5 - @get:JsonIgnore - var idleTimeout: Int = 99999 - - override fun toString(): String { - return "$ipAddress:$port" - } -} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/api/NetconfException.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/api/NetconfException.kt deleted file mode 100644 index d7642e75f..000000000 --- a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/api/NetconfException.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright © 2017-2019 AT&T, Bell Canada - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.api - -class NetconfException : Exception { - - constructor(cause: Throwable) : super(cause) - constructor(message: String) : super(message) - constructor(message: String, cause: Throwable) : super(message, cause) - -} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/api/NetconfMessage.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/api/NetconfMessage.kt deleted file mode 100644 index da7466143..000000000 --- a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/api/NetconfMessage.kt +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright © 2017-2019 AT&T, Bell Canada - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.api - -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.utils.RpcStatus - -class DeviceResponse { - var status: String? = null - var errorMessage: String? = null - var responseMessage: String? = null - var requestMessage: String? = null - private var subDeviceResponse: MutableMap? = null - - fun addSubDeviceResponse(key: String, subDeviceResponse: DeviceResponse) { - if (this.subDeviceResponse == null) { - this.subDeviceResponse = hashMapOf() - } - this.subDeviceResponse!![key] = subDeviceResponse - } - - fun isSuccess(): Boolean { - if (this.status != RpcStatus.SUCCESS && !this.errorMessage.isNullOrEmpty()) { - return false - } - return true - } -} - - -/** - * Creates an event of a given type and for the specified subject and the current time. - * - * @param type event type - * @param payload message from the device - * @param messageId id of the message related to the event - * @param deviceInfo device of event - */ -class NetconfReceivedEvent - (private var type: Type, private var payload: String = "", private var messageId: String = "", - private var deviceInfo: DeviceInfo) { - - enum class Type { - DEVICE_REPLY, - DEVICE_UNREGISTERED, - DEVICE_ERROR, - SESSION_CLOSED - } - - fun getType(): Type { - return type - } - - fun getMessagePayload(): String { - return payload - } - - fun getMessageID(): String { - return messageId - } -} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/api/NetconfRpcService.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/api/NetconfRpcService.kt deleted file mode 100644 index 02c0a3426..000000000 --- a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/api/NetconfRpcService.kt +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright © 2017-2018 AT&T Intellectual Property. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.api - -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.utils.ModifyAction -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.utils.NetconfDatastore - -interface NetconfRpcService { - - /** - * Lock - * - * @param configTarget running or candidate, default candidate - * @return Device response - */ - fun lock(configTarget: String = NetconfDatastore.CANDIDATE.datastore): DeviceResponse - - /** - * Get-config - * - * @param filter filter content, default empty - * @param configTarget running or candidate, default running - * @return Device response - */ - fun getConfig(filter: String = "", configTarget: String = NetconfDatastore.RUNNING.datastore): DeviceResponse - - /** - * Delete config - * - * @param configTarget running or candidate, default candidate - * @return Device response - */ - fun deleteConfig(configTarget: String = NetconfDatastore.CANDIDATE.datastore): DeviceResponse - - /** - * Edit-config - * - * @param messageContent edit config content. - * @param configTarget running or candidate, default candidate - * @param editDefaultOperation, default set to none. Valid values: merge, replace, create, delete, none - * @return Device response - */ - fun editConfig(messageContent: String, configTarget: String = NetconfDatastore.CANDIDATE.datastore, - editDefaultOperation: String = ModifyAction.NONE.action): DeviceResponse - - /** - * Invoke custom RPC as provided as input. - * - * Some use cases might required one to directly invoke a device - * specific RPC. The RPC must be correctly formatted. - * - * Ex: in order to rollback last submitted configuration - * for JUNOS devices, such RPC can be use: - * - * <rpc> - * <load-configuration rollback="1"/> - * </rpc> - * - * - * @param rpc the rpc content. - */ - fun invokeRpc(rpc: String): DeviceResponse - - /** - * Validate - * - * @param configTarget running or candidate, default candidate - * @return Device response - */ - fun validate(configTarget: String = NetconfDatastore.CANDIDATE.datastore): DeviceResponse - - /** - * Commit - * - * @param confirmed Perform a confirmed operation. If flag set to true, - * then it is expected to have a follow-up operation to confirm the request - * @param confirmTimeout Timeout period for confirmed commit, in seconds. - * @param persist Make the confirmed commit survive a session termination, and - * set a token on the ongoing confirmed commit. - * @param persistId Used to issue a follow-up confirmed commit or a confirming - * commit from any session, with the token from the previous operation. - * If unspecified, the confirm timeout defaults to 600 seconds. - * @return Device response - */ - fun commit(confirmed: Boolean = false, confirmTimeout: Int = 60, persist: String = "", - persistId: String = ""): DeviceResponse - - /** - * Cancels an ongoing confirmed commit. If the parameter is not given, - * the operation MUST be issued on the same session that issued - * the confirmed commit. - * - * @param persistId Cancels a persistent confirmed commit. The value MUST be equal - * to the value given in the parameter to the operation. - * If the value does not match, the operation fails with an "invalid-value" error. - */ - fun cancelCommit(persistId: String = ""): DeviceResponse - - /** - * Unlock - * - * @param configTarget running or candidate, default candidate - * @return Device response - */ - fun unLock(configTarget: String = NetconfDatastore.CANDIDATE.datastore): DeviceResponse - - /** - * Discard config - * - * @return Device response - */ - fun discardConfig(): DeviceResponse - - /** - * Close session - * - * @param force force closeSession - * @return Device response - */ - fun closeSession(force: Boolean): DeviceResponse - - /** - * Executes an RPC request to the netconf server. - * - * @param request the XML containing the RPC request for the server. - * @return Device response - */ - fun asyncRpc(request: String, messageId: String): DeviceResponse -} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/api/NetconfSession.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/api/NetconfSession.kt deleted file mode 100644 index 6a655d91f..000000000 --- a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/api/NetconfSession.kt +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright © 2017-2018 AT&T Intellectual Property. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.api - -import java.util.concurrent.CompletableFuture - -interface NetconfSession { - - /** - * Establish netconf session - */ - fun connect() - - - /** - * Disconnect netconf session - */ - fun disconnect() - - /** - * Reconnect netconf session - */ - fun reconnect() - - /** - * Executes an synchronous RPC request. - * - * @param request the XML request - * @param messageId message id of the request. - * @return Response - */ - @Throws(NetconfException::class) - fun syncRpc(request: String, messageId: String): String - - /** - * Executes an asynchronous RPC request. - * - * @param request the XML request - * @param messageId message id of the request. - * @return Response - */ - @Throws(NetconfException::class) - fun asyncRpc(request: String, messageId: String): CompletableFuture - - /** - * Checks the state of the underlying SSH session and connection and if necessary it reestablishes - * it. - */ - @Throws(NetconfException::class) - fun checkAndReestablish() - - /** - * Get the device information for initialised session. - * - * @return DeviceInfo as device information - */ - fun getDeviceInfo(): DeviceInfo - - /** - * Gets the session ID of the Netconf session. - * - * @return Session ID as a string. - */ - fun getSessionId(): String - - /** - * Gets the capabilities of the remote Netconf device associated to this session. - * - * @return Network capabilities as strings in a Set. - */ - fun getDeviceCapabilitiesSet(): Set -} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/api/NetconfSessionListener.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/api/NetconfSessionListener.kt deleted file mode 100644 index 8854894fa..000000000 --- a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/api/NetconfSessionListener.kt +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright © 2017-2019 AT&T, Bell Canada - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.api - -interface NetconfSessionListener { - - fun notify(event: NetconfReceivedEvent) -} diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/core/NetconfDeviceCommunicator.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/core/NetconfDeviceCommunicator.kt deleted file mode 100644 index 694756195..000000000 --- a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/core/NetconfDeviceCommunicator.kt +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright © 2017-2019 AT&T, Bell Canada - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.core - -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.api.DeviceInfo -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.api.NetconfReceivedEvent -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.api.NetconfSessionListener -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.utils.NetconfMessageUtils -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.utils.RpcMessageUtils -import org.slf4j.LoggerFactory -import java.io.BufferedReader -import java.io.IOException -import java.io.InputStream -import java.io.InputStreamReader -import java.io.OutputStream -import java.io.OutputStreamWriter -import java.nio.charset.StandardCharsets -import java.util.concurrent.CompletableFuture - -class NetconfDeviceCommunicator(private var inputStream: InputStream, - private var out: OutputStream, - private val deviceInfo: DeviceInfo, - private val sessionListener: NetconfSessionListener, - private var replies: MutableMap>) : Thread() { - - private val log = LoggerFactory.getLogger(NetconfDeviceCommunicator::class.java) - private var state = NetconfMessageState.NO_MATCHING_PATTERN - - init { - start() - } - - override fun run() { - var bufferReader: BufferedReader? = null - while (bufferReader == null) { - bufferReader = BufferedReader(InputStreamReader(inputStream, StandardCharsets.UTF_8)) - } - - try { - var socketClosed = false - val deviceReplyBuilder = StringBuilder() - while (!socketClosed) { - val cInt = bufferReader.read() - if (cInt == -1) { - log.error("$deviceInfo: Received cInt = -1") -// bufferReader.close() - socketClosed = true -// sessionListener.notify(NetconfReceivedEvent( -// NetconfReceivedEvent.Type.SESSION_CLOSED, -// deviceInfo = deviceInfo)) - } - val c = cInt.toChar() - state = state.evaluateChar(c) - deviceReplyBuilder.append(c) - if (state === NetconfMessageState.END_PATTERN) { - var deviceReply = deviceReplyBuilder.toString() - if (deviceReply == RpcMessageUtils.END_PATTERN) { - socketClosed = true - bufferReader.close() - sessionListener.notify(NetconfReceivedEvent( - NetconfReceivedEvent.Type.DEVICE_UNREGISTERED, - deviceInfo = deviceInfo)) - } else { - deviceReply = deviceReply.replace(RpcMessageUtils.END_PATTERN, "") - receivedMessage(deviceReply) - deviceReplyBuilder.setLength(0) - } - } else if (state === NetconfMessageState.END_CHUNKED_PATTERN) { - var deviceReply = deviceReplyBuilder.toString() - if (!NetconfMessageUtils.validateChunkedFraming(deviceReply)) { - log.debug("$deviceInfo: Received badly framed message $deviceReply") - socketClosed = true - sessionListener.notify(NetconfReceivedEvent( - NetconfReceivedEvent.Type.DEVICE_ERROR, - deviceInfo = deviceInfo)) - } else { - deviceReply = deviceReply.replace(RpcMessageUtils.MSGLEN_REGEX_PATTERN.toRegex(), "") - deviceReply = deviceReply.replace(NetconfMessageUtils.CHUNKED_END_REGEX_PATTERN.toRegex(), "") - receivedMessage(deviceReply) - deviceReplyBuilder.setLength(0) - } - } - } - - } catch (e: IOException) { - log.warn("$deviceInfo: Fail while reading from channel", e) - sessionListener.notify(NetconfReceivedEvent( - NetconfReceivedEvent.Type.DEVICE_ERROR, - deviceInfo = deviceInfo)) - } - - } - - private enum class NetconfMessageState { - NO_MATCHING_PATTERN { - override fun evaluateChar(c: Char): NetconfMessageState { - return if (c == ']') { - FIRST_BRACKET - } else if (c == '\n') { - FIRST_LF - } else { - this - } - } - }, - FIRST_BRACKET { - override fun evaluateChar(c: Char): NetconfMessageState { - return if (c == ']') { - SECOND_BRACKET - } else { - NO_MATCHING_PATTERN - } - } - }, - SECOND_BRACKET { - override fun evaluateChar(c: Char): NetconfMessageState { - return if (c == '>') { - FIRST_BIGGER - } else { - NO_MATCHING_PATTERN - } - } - }, - FIRST_BIGGER { - override fun evaluateChar(c: Char): NetconfMessageState { - return if (c == ']') { - THIRD_BRACKET - } else { - NO_MATCHING_PATTERN - } - } - }, - THIRD_BRACKET { - override fun evaluateChar(c: Char): NetconfMessageState { - return if (c == ']') { - ENDING_BIGGER - } else { - NO_MATCHING_PATTERN - } - } - }, - ENDING_BIGGER { - override fun evaluateChar(c: Char): NetconfMessageState { - return if (c == '>') { - END_PATTERN - } else { - NO_MATCHING_PATTERN - } - } - }, - FIRST_LF { - override fun evaluateChar(c: Char): NetconfMessageState { - return if (c == '#') { - FIRST_HASH - } else if (c == ']') { - FIRST_BRACKET - } else if (c == '\n') { - this - } else { - NO_MATCHING_PATTERN - } - } - }, - FIRST_HASH { - override fun evaluateChar(c: Char): NetconfMessageState { - return if (c == '#') { - SECOND_HASH - } else { - NO_MATCHING_PATTERN - } - } - }, - SECOND_HASH { - override fun evaluateChar(c: Char): NetconfMessageState { - return if (c == '\n') { - END_CHUNKED_PATTERN - } else { - NO_MATCHING_PATTERN - } - } - }, - END_CHUNKED_PATTERN { - override fun evaluateChar(c: Char): NetconfMessageState { - return NO_MATCHING_PATTERN - } - }, - END_PATTERN { - override fun evaluateChar(c: Char): NetconfMessageState { - return NO_MATCHING_PATTERN - } - }; - - internal abstract fun evaluateChar(c: Char): NetconfMessageState - } - - fun sendMessage(request: String, messageId: String): CompletableFuture { - log.info("$deviceInfo: Sending message: \n $request") - val future = CompletableFuture() - replies.put(messageId, future) - val outputStream = OutputStreamWriter(out, StandardCharsets.UTF_8) - synchronized(this) { - try { - outputStream.write(request) - outputStream.flush() - } catch (e: IOException) { - log.error("$deviceInfo: Failed to send message : \n $request", e) - future.completeExceptionally(e) - } - - } - return future - } - - private fun receivedMessage(deviceReply: String) { - if (deviceReply.contains(RpcMessageUtils.RPC_REPLY) || deviceReply.contains(RpcMessageUtils.RPC_ERROR) - || deviceReply.contains(RpcMessageUtils.HELLO)) { - log.info("$deviceInfo: Received message with messageId: {} \n $deviceReply", - NetconfMessageUtils.getMsgId(deviceReply)) - - } else { - log.error("$deviceInfo: Invalid message received: \n $deviceReply") - } - sessionListener.notify(NetconfReceivedEvent( - NetconfReceivedEvent.Type.DEVICE_REPLY, - deviceReply, - NetconfMessageUtils.getMsgId(deviceReply), - deviceInfo)) - } -} diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/core/NetconfRpcServiceImpl.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/core/NetconfRpcServiceImpl.kt deleted file mode 100644 index 15fb3122c..000000000 --- a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/core/NetconfRpcServiceImpl.kt +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright © 2017-2019 AT&T, Bell Canada - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.core - -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.api.DeviceInfo -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.api.DeviceResponse -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.api.NetconfException -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.api.NetconfRpcService -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.api.NetconfSession -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.utils.NetconfMessageUtils -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.utils.RpcStatus -import org.slf4j.LoggerFactory -import java.util.concurrent.TimeUnit -import java.util.concurrent.atomic.AtomicInteger - -class NetconfRpcServiceImpl(private var deviceInfo: DeviceInfo) : NetconfRpcService { - - private val log = LoggerFactory.getLogger(NetconfRpcService::class.java) - - private var responseTimeout: Int = deviceInfo.replyTimeout - - private lateinit var netconfSession: NetconfSession - - private val messageIdInteger = AtomicInteger(1) - - fun setNetconfSession(netconfSession: NetconfSession) { - this.netconfSession = netconfSession - } - - override fun invokeRpc(rpc: String): DeviceResponse { - var output = DeviceResponse() - val messageId = messageIdInteger.getAndIncrement().toString() - log.info("$deviceInfo: invokeRpc: messageId($messageId)") - try { - output = asyncRpc(rpc, messageId) - } catch (e: Exception) { - output.status = RpcStatus.FAILURE - output.errorMessage = "$deviceInfo: failed in invokeRpc command $e.message" - } - return output - } - - override fun getConfig(filter: String, configTarget: String): DeviceResponse { - var output = DeviceResponse() - val messageId = messageIdInteger.getAndIncrement().toString() - log.info("$deviceInfo: getConfig: messageId($messageId)") - try { - val message = NetconfMessageUtils.getConfig(messageId, configTarget, filter) - output = asyncRpc(message, messageId) - } catch (e: Exception) { - output.status = RpcStatus.FAILURE - output.errorMessage = "$deviceInfo: failed in get-config command $e.message" - } - return output - } - - override fun deleteConfig(configTarget: String): DeviceResponse { - var output = DeviceResponse() - val messageId = messageIdInteger.getAndIncrement().toString() - log.info("$deviceInfo: deleteConfig: messageId($messageId)") - try { - val deleteConfigMessage = NetconfMessageUtils.deleteConfig(messageId, configTarget) - output.requestMessage = deleteConfigMessage - output = asyncRpc(deleteConfigMessage, messageId) - } catch (e: Exception) { - output.status = RpcStatus.FAILURE - output.errorMessage = "$deviceInfo: failed in delete config command $e.message" - } - return output - } - - override fun lock(configTarget: String): DeviceResponse { - var output = DeviceResponse() - val messageId = messageIdInteger.getAndIncrement().toString() - log.info("$deviceInfo: lock: messageId($messageId)") - try { - val lockMessage = NetconfMessageUtils.lock(messageId, configTarget) - output.requestMessage = lockMessage - output = asyncRpc(lockMessage, messageId) - } catch (e: Exception) { - output.status = RpcStatus.FAILURE - output.errorMessage = "$deviceInfo: failed in lock command $e.message" - } - - return output - } - - override fun unLock(configTarget: String): DeviceResponse { - var output = DeviceResponse() - val messageId = messageIdInteger.getAndIncrement().toString() - log.info("$deviceInfo: unLock: messageId($messageId)") - try { - val unlockMessage = NetconfMessageUtils.unlock(messageId, configTarget) - output.requestMessage = unlockMessage - output = asyncRpc(unlockMessage, messageId) - } catch (e: Exception) { - output.status = RpcStatus.FAILURE - output.errorMessage = "$deviceInfo: failed in lock command $e.message" - } - return output - } - - override fun commit(confirmed: Boolean, confirmTimeout: Int, persist: String, persistId: String): DeviceResponse { - var output = DeviceResponse() - val messageId = messageIdInteger.getAndIncrement().toString() - log.info("$deviceInfo: commit: messageId($messageId)") - try { - val messageContent = NetconfMessageUtils.commit(messageId, confirmed, confirmTimeout, persist, persistId) - output = asyncRpc(messageContent, messageId) - } catch (e: Exception) { - output.status = RpcStatus.FAILURE - output.errorMessage = "$deviceInfo: failed in commit command $e.message" - } - return output - } - - override fun cancelCommit(persistId: String): DeviceResponse { - var output = DeviceResponse() - val messageId = messageIdInteger.getAndIncrement().toString() - log.info("$deviceInfo: cancelCommit: messageId($messageId)") - try { - val messageContent = NetconfMessageUtils.cancelCommit(messageId, persistId) - output = asyncRpc(messageContent, messageId) - } catch (e: Exception) { - output.status = RpcStatus.FAILURE - output.errorMessage = "$deviceInfo: failed in cancelCommit command $e.message" - } - return output - } - - override fun discardConfig(): DeviceResponse { - var output = DeviceResponse() - val messageId = messageIdInteger.getAndIncrement().toString() - log.info("$deviceInfo: discard: messageId($messageId)") - try { - val discardChangesMessage = NetconfMessageUtils.discardChanges(messageId) - output.requestMessage = discardChangesMessage - output = asyncRpc(discardChangesMessage, messageId) - } catch (e: Exception) { - output.status = RpcStatus.FAILURE - output.errorMessage = "$deviceInfo: failed in discard changes command " + e.message - } - return output - } - - override fun editConfig(messageContent: String, configTarget: String, - editDefaultOperation: String): DeviceResponse { - var response = DeviceResponse() - val messageId = messageIdInteger.getAndIncrement().toString() - log.info("$deviceInfo: editConfig: messageId($messageId)") - try { - val editMessage = - NetconfMessageUtils.editConfig(messageId, configTarget, editDefaultOperation, messageContent) - response.requestMessage = editMessage - response = asyncRpc(editMessage, messageId) - } catch (e: Exception) { - response.status = RpcStatus.FAILURE - response.errorMessage = e.message - } - return response - } - - override fun validate(configTarget: String): DeviceResponse { - var output = DeviceResponse() - val messageId = messageIdInteger.getAndIncrement().toString() - try { - val validateMessage = NetconfMessageUtils.validate(messageId, configTarget) - output.requestMessage = validateMessage - output = asyncRpc(validateMessage, messageId) - } catch (e: Exception) { - output.status = RpcStatus.FAILURE - output.errorMessage = "$deviceInfo: failed in validate command " + e.message - } - return output - } - - override fun closeSession(force: Boolean): DeviceResponse { - var output = DeviceResponse() - val messageId = messageIdInteger.getAndIncrement().toString() - log.info("$deviceInfo: closeSession: messageId($messageId)") - try { - val messageContent = NetconfMessageUtils.closeSession(messageId, force) - output = asyncRpc(messageContent, messageId) - } catch (e: Exception) { - output.status = RpcStatus.FAILURE - output.errorMessage = "$deviceInfo: failed in closeSession command " + e.message - } - return output - } - - @Throws(NetconfException::class) - override fun asyncRpc(request: String, messageId: String): DeviceResponse { - val response = DeviceResponse() - log.info("$deviceInfo: send asyncRpc with messageId($messageId)") - response.requestMessage = request - - val rpcResponse = netconfSession.asyncRpc(request, messageId).get(responseTimeout.toLong(), TimeUnit.SECONDS) - if (!NetconfMessageUtils.checkReply(rpcResponse)) { - throw NetconfException(rpcResponse) - } - response.responseMessage = rpcResponse - response.status = RpcStatus.SUCCESS - response.errorMessage = null - return response - } -} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/core/NetconfSessionImpl.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/core/NetconfSessionImpl.kt deleted file mode 100644 index 2dd73ef18..000000000 --- a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/core/NetconfSessionImpl.kt +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright © 2017-2019 AT&T, Bell Canada - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.core - -import com.google.common.collect.ImmutableList -import com.google.common.collect.ImmutableSet -import org.apache.sshd.client.SshClient -import org.apache.sshd.client.channel.ChannelSubsystem -import org.apache.sshd.client.channel.ClientChannel -import org.apache.sshd.client.session.ClientSession -import org.apache.sshd.client.session.ClientSessionImpl -import org.apache.sshd.common.FactoryManager -import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.api.DeviceInfo -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.api.NetconfException -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.api.NetconfReceivedEvent -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.api.NetconfRpcService -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.api.NetconfSession -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.api.NetconfSessionListener -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.utils.NetconfMessageUtils -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.utils.RpcMessageUtils -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.utils.RpcStatus -import org.slf4j.LoggerFactory -import java.io.IOException -import java.util.* -import java.util.concurrent.CompletableFuture -import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.ExecutionException -import java.util.concurrent.TimeUnit -import java.util.concurrent.TimeoutException -import java.util.concurrent.atomic.AtomicReference - -class NetconfSessionImpl(private val deviceInfo: DeviceInfo, private val rpcService: NetconfRpcService) : - NetconfSession { - - private val log = LoggerFactory.getLogger(NetconfSessionImpl::class.java) - - private val errorReplies: MutableList = Collections.synchronizedList(listOf()) - private val replies: MutableMap> = ConcurrentHashMap() - private val deviceCapabilities = setOf() - - private var connectionTimeout: Long = 0 - private var replyTimeout: Int = 0 - private var idleTimeout: Int = 0 - private var sessionId: String? = null - - private lateinit var session: ClientSession - private lateinit var client: SshClient - private lateinit var channel: ClientChannel - private lateinit var streamHandler: NetconfDeviceCommunicator - - private var capabilities = - ImmutableList.of(RpcMessageUtils.NETCONF_10_CAPABILITY, RpcMessageUtils.NETCONF_11_CAPABILITY) - - override fun connect() { - try { - log.info("$deviceInfo: Connecting to Netconf Device with timeouts C:${deviceInfo.connectTimeout}, " + - "R:${deviceInfo.replyTimeout}, I:${deviceInfo.idleTimeout}") - startConnection() - log.info("$deviceInfo: Connected to Netconf Device") - } catch (e: NetconfException) { - log.error("$deviceInfo: Netconf Device Connection Failed. ${e.message}") - throw NetconfException(e) - } - } - - override fun disconnect() { - if (rpcService.closeSession(false).status.equals( - RpcStatus.FAILURE, true)) { - rpcService.closeSession(true) - } - - session.close() - // Closes the socket which should interrupt the streamHandler - channel.close() - client.close() - } - - override fun reconnect() { - disconnect() - connect() - } - - override fun syncRpc(request: String, messageId: String): String { - val formattedRequest = NetconfMessageUtils.formatRPCRequest(request, messageId, deviceCapabilities) - - checkAndReestablish() - - try { - return streamHandler.sendMessage(formattedRequest, messageId).get(replyTimeout.toLong(), TimeUnit.SECONDS) -// replies.remove(messageId) - } catch (e: InterruptedException) { - Thread.currentThread().interrupt() - throw NetconfException("$deviceInfo: Interrupted while waiting for reply for request: $formattedRequest", e) - } catch (e: TimeoutException) { - throw NetconfException("$deviceInfo: Timed out while waiting for reply for request $formattedRequest after $replyTimeout sec.", - e) - } catch (e: ExecutionException) { - log.warn("$deviceInfo: Closing session($sessionId) due to unexpected Error", e) - try { - session.close() - // Closes the socket which should interrupt the streamHandler - channel.close() - client.close() - } catch (ioe: IOException) { - log.warn("$deviceInfo: Error closing session($sessionId) for host($deviceInfo)", ioe) - } - -// NetconfReceivedEvent(NetconfReceivedEvent.Type.SESSION_CLOSED, "", -// "Closed due to unexpected error " + e.cause, "-1", deviceInfo) - errorReplies.clear() // move to cleanUp()? - replies.clear() - - throw NetconfException("$deviceInfo: Closing session $sessionId for request $formattedRequest", e) - } - } - - override fun asyncRpc(request: String, messageId: String): CompletableFuture { - val formattedRequest = NetconfMessageUtils.formatRPCRequest(request, messageId, deviceCapabilities) - - checkAndReestablish() - - return streamHandler.sendMessage(formattedRequest, messageId).handleAsync { reply, t -> - if (t != null) { - throw NetconfException(messageId, t) - } - reply - } - } - - override fun checkAndReestablish() { - try { - if (client.isClosed) { - log.info("Trying to restart the whole SSH connection with {}", deviceInfo) - replies.clear() - startConnection() - } else if (session.isClosed) { - log.info("Trying to restart the session with {}", deviceInfo) - replies.clear() - startSession() - } else if (channel.isClosed) { - log.info("Trying to reopen the channel with {}", deviceInfo) - replies.clear() - openChannel() - } else { - return - } - } catch (e: IOException) { - log.error("Can't reopen connection for device {}", e.message) - throw NetconfException(String.format("Cannot re-open the connection with device (%s)", deviceInfo), e) - } catch (e: IllegalStateException) { - log.error("Can't reopen connection for device {}", e.message) - throw NetconfException(String.format("Cannot re-open the connection with device (%s)", deviceInfo), e) - } - - } - - override fun getDeviceInfo(): DeviceInfo { - return deviceInfo - } - - override fun getSessionId(): String { - return this.sessionId!! - } - - override fun getDeviceCapabilitiesSet(): Set { - return Collections.unmodifiableSet(deviceCapabilities) - } - - private fun startConnection() { - connectionTimeout = deviceInfo.connectTimeout - replyTimeout = deviceInfo.replyTimeout - idleTimeout = deviceInfo.idleTimeout - try { - startClient() - } catch (e: Exception) { - throw NetconfException("$deviceInfo: Failed to establish SSH session", e) - } - - } - - private fun startClient() { - client = SshClient.setUpDefaultClient() - client.properties.putIfAbsent(FactoryManager.IDLE_TIMEOUT, TimeUnit.SECONDS.toMillis(idleTimeout.toLong())) - client.properties.putIfAbsent(FactoryManager.NIO2_READ_TIMEOUT, TimeUnit.SECONDS.toMillis(idleTimeout + 15L)) - client.keyPairProvider = SimpleGeneratorHostKeyProvider() - client.start() - - startSession() - } - - private fun startSession() { - log.info("$deviceInfo: Starting SSH session") - val connectFuture = client.connect(deviceInfo.username, deviceInfo.ipAddress, deviceInfo.port) - .verify(connectionTimeout, TimeUnit.SECONDS) - session = connectFuture.session - log.info("$deviceInfo: SSH session created") - - authSession() - } - - private fun authSession() { - session.addPasswordIdentity(deviceInfo.password) - session.auth().verify(connectionTimeout, TimeUnit.SECONDS) - val event = session.waitFor(ImmutableSet.of(ClientSession.ClientSessionEvent.WAIT_AUTH, - ClientSession.ClientSessionEvent.CLOSED, ClientSession.ClientSessionEvent.AUTHED), 0) - if (!event.contains(ClientSession.ClientSessionEvent.AUTHED)) { - throw NetconfException("$deviceInfo: Failed to authenticate session.") - } - log.info("$deviceInfo: SSH session authenticated") - - openChannel() - } - - private fun openChannel() { - channel = session.createSubsystemChannel("netconf") - val channelFuture = channel.open() - if (channelFuture.await(connectionTimeout, TimeUnit.SECONDS) && channelFuture.isOpened) { - log.info("$deviceInfo: SSH NETCONF subsystem channel opened") - setupHandler() - } else { - throw NetconfException("$deviceInfo: Failed to open SSH subsystem channel") - } - } - - private fun setupHandler() { - val sessionListener: NetconfSessionListener = NetconfSessionListenerImpl() - streamHandler = NetconfDeviceCommunicator(channel.invertedOut, channel.invertedIn, deviceInfo, - sessionListener, replies) - - exchangeHelloMessage() - } - - private fun exchangeHelloMessage() { - sessionId = "-1" - val messageId = "-1" - - val serverHelloResponse = syncRpc(NetconfMessageUtils.createHelloString(capabilities), messageId) - val sessionIDMatcher = NetconfMessageUtils.SESSION_ID_REGEX_PATTERN.matcher(serverHelloResponse) - - if (sessionIDMatcher.find()) { - sessionId = sessionIDMatcher.group(1) - } else { - throw NetconfException("$deviceInfo: Missing sessionId in server hello message: $serverHelloResponse") - } - - val capabilityMatcher = NetconfMessageUtils.CAPABILITY_REGEX_PATTERN.matcher(serverHelloResponse) - while (capabilityMatcher.find()) { - deviceCapabilities.plus(capabilityMatcher.group(1)) - } - } - - inner class NetconfSessionListenerImpl : NetconfSessionListener { - override fun notify(event: NetconfReceivedEvent) { - val messageId = event.getMessageID() - - when (event.getType()) { - NetconfReceivedEvent.Type.DEVICE_UNREGISTERED -> disconnect() - NetconfReceivedEvent.Type.DEVICE_ERROR -> errorReplies.add(event.getMessagePayload()) - NetconfReceivedEvent.Type.DEVICE_REPLY -> replies[messageId]?.complete(event.getMessagePayload()) - NetconfReceivedEvent.Type.SESSION_CLOSED -> disconnect() - } - } - } - - fun sessionstatus(state:String): Boolean{ - return when (state){ - "Close" -> channel.isClosed - "Open" -> channel.isOpen - else -> false - } - } -} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/utils/NetconfConstant.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/utils/NetconfConstant.kt deleted file mode 100644 index 3b3b0c025..000000000 --- a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/utils/NetconfConstant.kt +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright © 2017-2019 AT&T, Bell Canada - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.utils - -enum class NetconfDatastore(val datastore: String) { - RUNNING("running"), - CANDIDATE("candidate"); -} - -enum class ModifyAction(val action: String) { - MERGE("merge"), - REPLACE("replace"), - NONE("none") -} - -object RpcStatus { - const val SUCCESS = "success" - const val FAILURE = "failure" -} - -object RpcMessageUtils { - const val OPEN = "<" - const val CLOSE = ">" - const val EQUAL = "=" - - const val HASH = "#" - const val HASH_CHAR = '#' - - const val LF_CHAR = '\n' - const val NEW_LINE = "\n" - - const val QUOTE = "\"" - const val QUOTE_SPACE = "\" " - - const val TAG_CLOSE = "/>" - const val END_OF_RPC_OPEN_TAG = "\">" - const val END_PATTERN = "]]>]]>" - - const val HELLO = "hello" - const val RPC_REPLY = "rpc-reply" - const val RPC_ERROR = "rpc-error" - - const val RPC_OPEN = "" - const val SUBTREE_FILTER_CLOSE = "" - const val TARGET_OPEN = "" - const val TARGET_CLOSE = "" - const val SOURCE_OPEN = "" - const val SOURCE_CLOSE = "" - const val CONFIG_OPEN = "" - const val CONFIG_CLOSE = "" - const val MSGLEN_REGEX_PATTERN = "\n#\\d+\n" - - const val NUMBER_BETWEEN_QUOTES_MATCHER = "\"+([0-9]+)+\"" - - const val XML_HEADER = "" - const val NETCONF_BASE_NAMESPACE = "xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"" - const val NETCONF_WITH_DEFAULTS_NAMESPACE = "xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\"" - const val SUBSCRIPTION_SUBTREE_FILTER_OPEN = - "" - - const val INTERLEAVE_CAPABILITY_STRING = "urn:ietf:params:netconf:capability:interleave:1.0" - - const val CAPABILITY_REGEX = "capability>\\s*(.*?)\\s*capability>" - - const val SESSION_ID_REGEX = "session-id>\\s*(.*?)\\s*session-id>" - - const val MESSAGE_ID_STRING = "message-id" - - const val NETCONF_10_CAPABILITY = "urn:ietf:params:netconf:base:1.0" - const val NETCONF_11_CAPABILITY = "urn:ietf:params:netconf:base:1.1" -} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/utils/NetconfMessageUtils.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/utils/NetconfMessageUtils.kt deleted file mode 100644 index 4de3860c5..000000000 --- a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/utils/NetconfMessageUtils.kt +++ /dev/null @@ -1,404 +0,0 @@ -/* - * Copyright © 2017-2019 AT&T, Bell Canada - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.utils - -import org.apache.commons.lang3.StringUtils -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.api.NetconfException -import org.slf4j.LoggerFactory -import org.xml.sax.InputSource -import java.io.StringReader -import java.nio.charset.StandardCharsets -import java.util.regex.MatchResult -import java.util.regex.Pattern -import javax.xml.XMLConstants -import javax.xml.parsers.DocumentBuilderFactory -import kotlin.text.Charsets.UTF_8 - - -class NetconfMessageUtils { - - companion object { - val log = LoggerFactory.getLogger(NetconfMessageUtils::class.java) - - const val NEW_LINE = "\n" - const val CHUNKED_END_REGEX_PATTERN = "\n##\n" - - val CAPABILITY_REGEX_PATTERN: Pattern = Pattern.compile(RpcMessageUtils.CAPABILITY_REGEX) - val SESSION_ID_REGEX_PATTERN: Pattern = Pattern.compile(RpcMessageUtils.SESSION_ID_REGEX) - - private val CHUNKED_FRAMING_PATTERN: Pattern = - Pattern.compile("(\\n#([1-9][0-9]*)\\n(.+))+\\n##\\n", Pattern.DOTALL) - private val CHUNKED_SIZE_PATTERN: Pattern = Pattern.compile("\\n#([1-9][0-9]*)\\n") - private val MSG_ID_STRING_PATTERN = Pattern.compile("${RpcMessageUtils.MESSAGE_ID_STRING}=\"(.*?)\"") - - fun getConfig(messageId: String, configType: String, filterContent: String?): String { - val request = StringBuilder() - - request.append("").append(NEW_LINE) - request.append(RpcMessageUtils.SOURCE_OPEN).append(NEW_LINE) - request.append(RpcMessageUtils.OPEN).append(configType).append(RpcMessageUtils.TAG_CLOSE) - .append(NEW_LINE) - request.append(RpcMessageUtils.SOURCE_CLOSE).append(NEW_LINE) - - if (!filterContent.isNullOrEmpty()) { - request.append(RpcMessageUtils.SUBTREE_FILTER_OPEN).append(NEW_LINE) - request.append(filterContent).append(NEW_LINE) - request.append(RpcMessageUtils.SUBTREE_FILTER_CLOSE).append(NEW_LINE) - } - request.append("").append(NEW_LINE) - - return doWrappedRpc(messageId, request.toString()) - } - - fun doWrappedRpc(messageId: String, request: String): String { - val rpc = StringBuilder(RpcMessageUtils.XML_HEADER).append(NEW_LINE) - rpc.append(RpcMessageUtils.RPC_OPEN) - rpc.append(RpcMessageUtils.MESSAGE_ID_STRING).append(RpcMessageUtils.EQUAL) - rpc.append(RpcMessageUtils.QUOTE).append(messageId).append(RpcMessageUtils.QUOTE_SPACE) - rpc.append(RpcMessageUtils.NETCONF_BASE_NAMESPACE).append(RpcMessageUtils.CLOSE) - .append(NEW_LINE) - rpc.append(request) - rpc.append(RpcMessageUtils.RPC_CLOSE) - // rpc.append(NEW_LINE).append(END_PATTERN); - - return rpc.toString() - } - - fun editConfig(messageId: String, configType: String, defaultOperation: String?, - newConfiguration: String): String { - - val request = StringBuilder() - - request.append("").append(NEW_LINE) - request.append(RpcMessageUtils.TARGET_OPEN).append(NEW_LINE) - request.append(RpcMessageUtils.OPEN).append(configType).append(RpcMessageUtils.TAG_CLOSE) - .append(NEW_LINE) - request.append(RpcMessageUtils.TARGET_CLOSE).append(NEW_LINE) - - if (defaultOperation != null) { - request.append(RpcMessageUtils.DEFAULT_OPERATION_OPEN).append(defaultOperation) - .append(RpcMessageUtils.DEFAULT_OPERATION_CLOSE) - request.append(NEW_LINE) - } - - request.append(RpcMessageUtils.CONFIG_OPEN).append(NEW_LINE) - request.append(newConfiguration.trim { it <= ' ' }).append(NEW_LINE) - request.append(RpcMessageUtils.CONFIG_CLOSE).append(NEW_LINE) - request.append("").append(NEW_LINE) - - return doWrappedRpc(messageId, request.toString()) - } - - fun validate(messageId: String, configType: String): String { - val request = StringBuilder() - - request.append("").append(NEW_LINE) - request.append(RpcMessageUtils.SOURCE_OPEN).append(NEW_LINE) - request.append(RpcMessageUtils.OPEN).append(configType).append(RpcMessageUtils.TAG_CLOSE) - .append(NEW_LINE) - request.append(RpcMessageUtils.SOURCE_CLOSE).append(NEW_LINE) - request.append("").append(NEW_LINE) - - return doWrappedRpc(messageId, request.toString()) - } - - fun commit(messageId: String, confirmed: Boolean, confirmTimeout: Int, persist: String, - persistId: String): String { - - if (!persist.isEmpty() && !persistId.isEmpty()) { - throw NetconfException("Can't proceed with both persist($persist) and " + - "persistId($persistId) specified. Only one should be specified.") - } - if (confirmed && !persistId.isEmpty()) { - throw NetconfException("Can't proceed with both confirmed flag and " + - "persistId($persistId) specified. Only one should be specified.") - } - - val request = StringBuilder() - request.append("").append(NEW_LINE) - if (confirmed) { - request.append("") - request.append("$confirmTimeout") - if (!persist.isEmpty()) { - request.append("$persist") - } - } - if (!persistId.isEmpty()) { - request.append("$persistId") - } - request.append("").append(NEW_LINE) - - return doWrappedRpc(messageId, request.toString()) - } - - fun cancelCommit(messageId: String, persistId: String): String { - val request = StringBuilder() - request.append("").append(NEW_LINE) - if (!persistId.isEmpty()) { - request.append("$persistId") - } - request.append("").append(NEW_LINE) - - return doWrappedRpc(messageId, request.toString()) - } - - fun unlock(messageId: String, configType: String): String { - val request = StringBuilder() - - request.append("").append(NEW_LINE) - request.append(RpcMessageUtils.TARGET_OPEN).append(NEW_LINE) - request.append(RpcMessageUtils.OPEN).append(configType).append(RpcMessageUtils.TAG_CLOSE) - .append(NEW_LINE) - request.append(RpcMessageUtils.TARGET_CLOSE).append(NEW_LINE) - request.append("").append(NEW_LINE) - - return doWrappedRpc(messageId, request.toString()) - } - - @Throws(NetconfException::class) - fun deleteConfig(messageId: String, configType: String): String { - if (configType == NetconfDatastore.RUNNING.datastore) { - log.warn("Target configuration for delete operation can't be \"running\" {}", configType) - throw NetconfException("Target configuration for delete operation can't be running") - } - - val request = StringBuilder() - - request.append("").append(NEW_LINE) - request.append(RpcMessageUtils.TARGET_OPEN).append(NEW_LINE) - request.append(RpcMessageUtils.OPEN).append(configType) - .append(RpcMessageUtils.TAG_CLOSE) - .append(NEW_LINE) - request.append(RpcMessageUtils.TARGET_CLOSE).append(NEW_LINE) - request.append("").append(NEW_LINE) - - return doWrappedRpc(messageId, request.toString()) - } - - fun discardChanges(messageId: String): String { - val request = StringBuilder() - request.append("").append(NEW_LINE) - return doWrappedRpc(messageId, request.toString()) - } - - fun lock(messageId: String, configType: String): String { - val request = StringBuilder() - - request.append("").append(NEW_LINE) - request.append(RpcMessageUtils.TARGET_OPEN).append(NEW_LINE) - request.append(RpcMessageUtils.OPEN).append(configType).append(RpcMessageUtils.TAG_CLOSE) - .append(NEW_LINE) - request.append(RpcMessageUtils.TARGET_CLOSE).append(NEW_LINE) - request.append("").append(NEW_LINE) - - return doWrappedRpc(messageId, request.toString()) - } - - fun closeSession(messageId: String, force: Boolean): String { - val request = StringBuilder() - - if (force) { - request.append("").append(NEW_LINE) - } else { - request.append("").append(NEW_LINE) - } - - return doWrappedRpc(messageId, request.toString()) - } - - fun validateRPCXML(rpcRequest: String): Boolean { - try { - if (StringUtils.isBlank(rpcRequest)) { - return false - } - val dbf = DocumentBuilderFactory.newInstance() - dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true) - dbf.setFeature("http://xml.org/sax/features/external-general-entities", false) - dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false) - dbf.newDocumentBuilder() - .parse(InputSource(StringReader(rpcRequest.replace(RpcMessageUtils.END_PATTERN, "")))) - return true - } catch (e: Exception) { - return false - } - - } - - fun getMsgId(message: String): String { - val matcher = MSG_ID_STRING_PATTERN.matcher(message) - if (matcher.find()) { - return matcher.group(1) - } - return if (message.contains(RpcMessageUtils.HELLO)) { - (-1).toString() - } else "" - } - - fun validateChunkedFraming(reply: String): Boolean { - val matcher = CHUNKED_FRAMING_PATTERN.matcher(reply) - if (!matcher.matches()) { - log.debug("Error Reply: {}", reply) - return false - } - val chunkM = CHUNKED_SIZE_PATTERN.matcher(reply) - val chunks = ArrayList() - var chunkdataStr = "" - while (chunkM.find()) { - chunks.add(chunkM.toMatchResult()) - // extract chunk-data (and later) in bytes - val bytes = Integer.parseInt(chunkM.group(1)) - val chunkdata = reply.substring(chunkM.end()).toByteArray(StandardCharsets.UTF_8) - if (bytes > chunkdata.size) { - log.debug("Error Reply - wrong chunk size {}", reply) - return false - } - // convert (only) chunk-data part into String - chunkdataStr = String(chunkdata, 0, bytes, StandardCharsets.UTF_8) - // skip chunk-data part from next match - chunkM.region(chunkM.end() + chunkdataStr.length, reply.length) - } - if (!CHUNKED_END_REGEX_PATTERN.equals(reply.substring(chunks[chunks.size - 1].end() + chunkdataStr.length))) { - log.debug("Error Reply: {}", reply) - return false - } - return true - } - - fun createHelloString(capabilities: List): String { - val helloMessage = StringBuilder() - helloMessage.append(RpcMessageUtils.XML_HEADER).append(NEW_LINE) - helloMessage.append("").append(NEW_LINE) - helloMessage.append(" ").append(NEW_LINE) - if (capabilities.isNotEmpty()) { - capabilities.forEach { cap -> - helloMessage.append(" ").append(cap).append("").append(NEW_LINE) - } - } - helloMessage.append(" ").append(NEW_LINE) - helloMessage.append("").append(NEW_LINE) - helloMessage.append(RpcMessageUtils.END_PATTERN) - return helloMessage.toString() - } - - fun formatRPCRequest(request: String, messageId: String, deviceCapabilities: Set): String { - var request = request - request = NetconfMessageUtils.formatNetconfMessage(deviceCapabilities, request) - request = NetconfMessageUtils.formatXmlHeader(request) - request = NetconfMessageUtils.formatRequestMessageId(request, messageId) - - return request - } - - /** - * Validate and format netconf message. - NC1.0 if no EOM sequence present on `message`, - * append. - NC1.1 chunk-encode given message unless it already is chunk encoded - * - * @param deviceCapabilities Set containing Device Capabilities - * @param message to format - * @return formated message - */ - fun formatNetconfMessage(deviceCapabilities: Set, message: String): String { - var message = message - if (deviceCapabilities.contains(RpcMessageUtils.NETCONF_11_CAPABILITY)) { - message = formatChunkedMessage(message) - } else if (!message.endsWith(RpcMessageUtils.END_PATTERN)) { - message = message + NEW_LINE + RpcMessageUtils.END_PATTERN - } - return message - } - - /** - * Validate and format message according to chunked framing mechanism. - * - * @param message to format - * @return formated message - */ - fun formatChunkedMessage(message: String): String { - var message = message - if (message.endsWith(RpcMessageUtils.END_PATTERN)) { - // message given had Netconf 1.0 EOM pattern -> remove - message = message.substring(0, message.length - RpcMessageUtils.END_PATTERN.length) - } - if (!message.startsWith(RpcMessageUtils.NEW_LINE + RpcMessageUtils.HASH)) { - // chunk encode message - message = - (RpcMessageUtils.NEW_LINE + RpcMessageUtils.HASH + message.toByteArray(UTF_8).size + RpcMessageUtils.NEW_LINE + message + RpcMessageUtils.NEW_LINE + RpcMessageUtils.HASH + RpcMessageUtils.HASH - + RpcMessageUtils.NEW_LINE) - } - return message - } - - /** - * Ensures xml start directive/declaration appears in the `request`. - * - * @param request RPC request message - * @return XML RPC message - */ - fun formatXmlHeader(request: String): String { - var request = request - if (!request.contains(RpcMessageUtils.XML_HEADER)) { - if (request.startsWith(RpcMessageUtils.NEW_LINE + RpcMessageUtils.HASH)) { - request = - request.split("<".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[0] + RpcMessageUtils.XML_HEADER + request.substring( - request.split("<".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[0].length) - } else { - request = RpcMessageUtils.XML_HEADER + "\n" + request - } - } - return request - } - - fun formatRequestMessageId(request: String, messageId: String): String { - var request = request - if (request.contains(RpcMessageUtils.MESSAGE_ID_STRING)) { - request = - request.replaceFirst((RpcMessageUtils.MESSAGE_ID_STRING + RpcMessageUtils.EQUAL + RpcMessageUtils.NUMBER_BETWEEN_QUOTES_MATCHER).toRegex(), - RpcMessageUtils.MESSAGE_ID_STRING + RpcMessageUtils.EQUAL + RpcMessageUtils.QUOTE + messageId + RpcMessageUtils.QUOTE) - } else if (!request.contains(RpcMessageUtils.MESSAGE_ID_STRING) && !request.contains( - RpcMessageUtils.HELLO)) { - request = request.replaceFirst(RpcMessageUtils.END_OF_RPC_OPEN_TAG.toRegex(), - RpcMessageUtils.QUOTE_SPACE + RpcMessageUtils.MESSAGE_ID_STRING + RpcMessageUtils.EQUAL + RpcMessageUtils.QUOTE + messageId + RpcMessageUtils.QUOTE + ">") - } - return updateRequestLength(request) - } - - fun updateRequestLength(request: String): String { - if (request.contains(NEW_LINE + RpcMessageUtils.HASH + RpcMessageUtils.HASH + NEW_LINE)) { - val oldLen = - Integer.parseInt(request.split(RpcMessageUtils.HASH.toRegex()).dropLastWhile({ it.isEmpty() }).toTypedArray()[1].split( - NEW_LINE.toRegex()).dropLastWhile({ it.isEmpty() }).toTypedArray()[0]) - val rpcWithEnding = request.substring(request.indexOf('<')) - val firstBlock = - request.split(RpcMessageUtils.MSGLEN_REGEX_PATTERN.toRegex()).dropLastWhile({ it.isEmpty() }).toTypedArray()[1].split( - (NEW_LINE + RpcMessageUtils.HASH + RpcMessageUtils.HASH + NEW_LINE).toRegex()).dropLastWhile( - { it.isEmpty() }).toTypedArray()[0] - var newLen = 0 - newLen = firstBlock.toByteArray(UTF_8).size - if (oldLen != newLen) { - return NEW_LINE + RpcMessageUtils.HASH + newLen + NEW_LINE + rpcWithEnding - } - } - return request - } - - fun checkReply(reply: String?): Boolean { - return if (reply != null) { - !reply.contains("rpc-error>") || reply.contains("warning") || reply.contains("ok/>") - } else false - } - } - -} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/ComponentNetconfExecutor.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/ComponentNetconfExecutor.kt new file mode 100644 index 000000000..2980de98a --- /dev/null +++ b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/ComponentNetconfExecutor.kt @@ -0,0 +1,75 @@ +/* + * Copyright © 2017-2018 AT&T Intellectual Property. + * + * Modifications Copyright © 2019 IBM, Bell Canada. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor + +import com.fasterxml.jackson.databind.node.ArrayNode +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput +import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants +import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractComponentFunction +import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ComponentFunctionScriptingService +import org.onap.ccsdk.cds.controllerblueprints.core.getAsString +import org.slf4j.LoggerFactory +import org.springframework.beans.factory.config.ConfigurableBeanFactory +import org.springframework.context.annotation.Scope +import org.springframework.stereotype.Component + +@Component("component-netconf-executor") +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +open class ComponentNetconfExecutor(private var componentFunctionScriptingService: ComponentFunctionScriptingService) + : AbstractComponentFunction() { + + private val log = LoggerFactory.getLogger(ComponentNetconfExecutor::class.java) + + companion object { + const val SCRIPT_TYPE = "script-type" + const val SCRIPT_CLASS_REFERENCE = "script-class-reference" + const val INSTANCE_DEPENDENCIES = "instance-dependencies" + } + + + lateinit var scriptComponent: NetconfComponentFunction + + override fun process(executionRequest: ExecutionServiceInput) { + + val scriptType = operationInputs.getAsString(SCRIPT_TYPE) + val scriptClassReference = operationInputs.getAsString(SCRIPT_CLASS_REFERENCE) + val instanceDependenciesNode = operationInputs.get(INSTANCE_DEPENDENCIES) as? ArrayNode + + val scriptDependencies: MutableList = arrayListOf() + scriptDependencies.add(ResourceResolutionConstants.SERVICE_RESOURCE_RESOLUTION) + + instanceDependenciesNode?.forEach { instanceName -> + scriptDependencies.add(instanceName.textValue()) + } + + scriptComponent = componentFunctionScriptingService.scriptInstance(this, scriptType, + scriptClassReference, scriptDependencies) + + + checkNotNull(scriptComponent) { "failed to get netconf script component" } + + scriptComponent.process(executionServiceInput) + } + + override fun recover(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) { + scriptComponent.recover(runtimeException, executionRequest) + } + + +} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/JsonParserService.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/JsonParserService.kt new file mode 100644 index 000000000..73c82acb2 --- /dev/null +++ b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/JsonParserService.kt @@ -0,0 +1,24 @@ +/* + * Copyright © 2017-2018 AT&T Intellectual Property. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor + +import org.springframework.stereotype.Service + +@Service("json-parser-service") +class JsonParserService { + +} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/NetconfComponentFunction.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/NetconfComponentFunction.kt new file mode 100644 index 000000000..4b08ce8e2 --- /dev/null +++ b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/NetconfComponentFunction.kt @@ -0,0 +1,70 @@ +/* + * Copyright © 2018-2019 IBM, Bell Canada. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor + +import com.fasterxml.jackson.databind.JsonNode +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.DeviceInfo +import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants +import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionService +import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractScriptComponentFunction +import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils + +abstract class NetconfComponentFunction : AbstractScriptComponentFunction() { + + open fun resourceResolutionService(): ResourceResolutionService = + functionDependencyInstanceAsType(ResourceResolutionConstants.SERVICE_RESOURCE_RESOLUTION) + + // Called from python script + fun initializeNetconfConnection(requirementName: String): NetconfDevice { + val deviceInfo = deviceProperties(requirementName) + return NetconfDevice(deviceInfo) + } + + fun generateMessage(artifactName: String): String { + return bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactName) + } + + fun resolveFromDatabase(resolutionKey: String, artifactName: String): String { + return resourceResolutionService().resolveFromDatabase(bluePrintRuntimeService, artifactName, resolutionKey) + } + + fun resolveAndGenerateMessage(artifactMapping: String, artifactTemplate: String): String { + return resourceResolutionService().resolveResources(bluePrintRuntimeService, nodeTemplateName, + artifactMapping, artifactTemplate) + } + + fun resolveAndGenerateMessage(artifactPrefix: String): String { + return resourceResolutionService().resolveResources(bluePrintRuntimeService, nodeTemplateName, + artifactPrefix, mapOf()) + } + + private fun deviceProperties(requirementName: String): DeviceInfo { + + val blueprintContext = bluePrintRuntimeService.bluePrintContext() + + val requirement = blueprintContext.nodeTemplateRequirement(nodeTemplateName, requirementName) + + val capabilityProperties = bluePrintRuntimeService.resolveNodeTemplateCapabilityProperties(requirement + .node!!, requirement.capability!!) + + return deviceProperties(capabilityProperties) + } + + private fun deviceProperties(capabilityProperty: MutableMap): DeviceInfo { + return JacksonUtils.getInstanceFromMap(capabilityProperty, DeviceInfo::class.java) + } +} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/NetconfDevice.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/NetconfDevice.kt new file mode 100644 index 000000000..61090f485 --- /dev/null +++ b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/NetconfDevice.kt @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2019 Bell Canada. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor + +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.DeviceInfo +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.NetconfSession +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.core.NetconfRpcServiceImpl +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.core.NetconfSessionImpl + +data class NetconfDevice(val deviceInfo: DeviceInfo) { + val netconfRpcService = NetconfRpcServiceImpl(deviceInfo) + val netconfSession: NetconfSession + + init { + netconfSession = NetconfSessionImpl(deviceInfo, netconfRpcService) + netconfRpcService.setNetconfSession(netconfSession) + } +} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/DeviceInfo.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/DeviceInfo.kt new file mode 100644 index 000000000..5eeaf6046 --- /dev/null +++ b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/DeviceInfo.kt @@ -0,0 +1,43 @@ +/* + * Copyright © 2017-2018 AT&T Intellectual Property. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api + +import com.fasterxml.jackson.annotation.JsonIgnore +import com.fasterxml.jackson.annotation.JsonProperty + +class DeviceInfo { + @get:JsonProperty("login-account") + var username: String? = null + @get:JsonProperty("login-key") + var password: String? = null + @get:JsonProperty("target-ip-address") + var ipAddress: String? = null + @get:JsonProperty("port-number") + var port: Int = 0 + @get:JsonProperty("connection-time-out") + var connectTimeout: Long = 5 + @get:JsonIgnore + var source: String? = null + @get:JsonIgnore + var replyTimeout: Int = 5 + @get:JsonIgnore + var idleTimeout: Int = 99999 + + override fun toString(): String { + return "$ipAddress:$port" + } +} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/NetconfException.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/NetconfException.kt new file mode 100644 index 000000000..7e6a88b48 --- /dev/null +++ b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/NetconfException.kt @@ -0,0 +1,24 @@ +/* + * Copyright © 2017-2019 AT&T, Bell Canada + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api + +class NetconfException : Exception { + + constructor(cause: Throwable) : super(cause) + constructor(message: String) : super(message) + constructor(message: String, cause: Throwable) : super(message, cause) + +} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/NetconfMessage.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/NetconfMessage.kt new file mode 100644 index 000000000..ef3605c66 --- /dev/null +++ b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/NetconfMessage.kt @@ -0,0 +1,74 @@ +/* + * Copyright © 2017-2019 AT&T, Bell Canada + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api + +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.utils.RpcStatus + +class DeviceResponse { + var status: String? = null + var errorMessage: String? = null + var responseMessage: String? = null + var requestMessage: String? = null + private var subDeviceResponse: MutableMap? = null + + fun addSubDeviceResponse(key: String, subDeviceResponse: DeviceResponse) { + if (this.subDeviceResponse == null) { + this.subDeviceResponse = hashMapOf() + } + this.subDeviceResponse!![key] = subDeviceResponse + } + + fun isSuccess(): Boolean { + if (this.status != RpcStatus.SUCCESS && !this.errorMessage.isNullOrEmpty()) { + return false + } + return true + } +} + + +/** + * Creates an event of a given type and for the specified subject and the current time. + * + * @param type event type + * @param payload message from the device + * @param messageId id of the message related to the event + * @param deviceInfo device of event + */ +class NetconfReceivedEvent + (private var type: Type, private var payload: String = "", private var messageId: String = "", + private var deviceInfo: DeviceInfo) { + + enum class Type { + DEVICE_REPLY, + DEVICE_UNREGISTERED, + DEVICE_ERROR, + SESSION_CLOSED + } + + fun getType(): Type { + return type + } + + fun getMessagePayload(): String { + return payload + } + + fun getMessageID(): String { + return messageId + } +} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/NetconfRpcService.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/NetconfRpcService.kt new file mode 100644 index 000000000..60345b5a6 --- /dev/null +++ b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/NetconfRpcService.kt @@ -0,0 +1,142 @@ +/* + * Copyright © 2017-2018 AT&T Intellectual Property. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api + +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.utils.ModifyAction +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.utils.NetconfDatastore + +interface NetconfRpcService { + + /** + * Lock + * + * @param configTarget running or candidate, default candidate + * @return Device response + */ + fun lock(configTarget: String = NetconfDatastore.CANDIDATE.datastore): DeviceResponse + + /** + * Get-config + * + * @param filter filter content, default empty + * @param configTarget running or candidate, default running + * @return Device response + */ + fun getConfig(filter: String = "", configTarget: String = NetconfDatastore.RUNNING.datastore): DeviceResponse + + /** + * Delete config + * + * @param configTarget running or candidate, default candidate + * @return Device response + */ + fun deleteConfig(configTarget: String = NetconfDatastore.CANDIDATE.datastore): DeviceResponse + + /** + * Edit-config + * + * @param messageContent edit config content. + * @param configTarget running or candidate, default candidate + * @param editDefaultOperation, default set to none. Valid values: merge, replace, create, delete, none + * @return Device response + */ + fun editConfig(messageContent: String, configTarget: String = NetconfDatastore.CANDIDATE.datastore, + editDefaultOperation: String = ModifyAction.NONE.action): DeviceResponse + + /** + * Invoke custom RPC as provided as input. + * + * Some use cases might required one to directly invoke a device + * specific RPC. The RPC must be correctly formatted. + * + * Ex: in order to rollback last submitted configuration + * for JUNOS devices, such RPC can be use: + * + * <rpc> + * <load-configuration rollback="1"/> + * </rpc> + * + * + * @param rpc the rpc content. + */ + fun invokeRpc(rpc: String): DeviceResponse + + /** + * Validate + * + * @param configTarget running or candidate, default candidate + * @return Device response + */ + fun validate(configTarget: String = NetconfDatastore.CANDIDATE.datastore): DeviceResponse + + /** + * Commit + * + * @param confirmed Perform a confirmed operation. If flag set to true, + * then it is expected to have a follow-up operation to confirm the request + * @param confirmTimeout Timeout period for confirmed commit, in seconds. + * @param persist Make the confirmed commit survive a session termination, and + * set a token on the ongoing confirmed commit. + * @param persistId Used to issue a follow-up confirmed commit or a confirming + * commit from any session, with the token from the previous operation. + * If unspecified, the confirm timeout defaults to 600 seconds. + * @return Device response + */ + fun commit(confirmed: Boolean = false, confirmTimeout: Int = 60, persist: String = "", + persistId: String = ""): DeviceResponse + + /** + * Cancels an ongoing confirmed commit. If the parameter is not given, + * the operation MUST be issued on the same session that issued + * the confirmed commit. + * + * @param persistId Cancels a persistent confirmed commit. The value MUST be equal + * to the value given in the parameter to the operation. + * If the value does not match, the operation fails with an "invalid-value" error. + */ + fun cancelCommit(persistId: String = ""): DeviceResponse + + /** + * Unlock + * + * @param configTarget running or candidate, default candidate + * @return Device response + */ + fun unLock(configTarget: String = NetconfDatastore.CANDIDATE.datastore): DeviceResponse + + /** + * Discard config + * + * @return Device response + */ + fun discardConfig(): DeviceResponse + + /** + * Close session + * + * @param force force closeSession + * @return Device response + */ + fun closeSession(force: Boolean): DeviceResponse + + /** + * Executes an RPC request to the netconf server. + * + * @param request the XML containing the RPC request for the server. + * @return Device response + */ + fun asyncRpc(request: String, messageId: String): DeviceResponse +} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/NetconfSession.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/NetconfSession.kt new file mode 100644 index 000000000..0272d1a19 --- /dev/null +++ b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/NetconfSession.kt @@ -0,0 +1,86 @@ +/* + * Copyright © 2017-2018 AT&T Intellectual Property. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api + +import java.util.concurrent.CompletableFuture + +interface NetconfSession { + + /** + * Establish netconf session + */ + fun connect() + + + /** + * Disconnect netconf session + */ + fun disconnect() + + /** + * Reconnect netconf session + */ + fun reconnect() + + /** + * Executes an synchronous RPC request. + * + * @param request the XML request + * @param messageId message id of the request. + * @return Response + */ + @Throws(NetconfException::class) + fun syncRpc(request: String, messageId: String): String + + /** + * Executes an asynchronous RPC request. + * + * @param request the XML request + * @param messageId message id of the request. + * @return Response + */ + @Throws(NetconfException::class) + fun asyncRpc(request: String, messageId: String): CompletableFuture + + /** + * Checks the state of the underlying SSH session and connection and if necessary it reestablishes + * it. + */ + @Throws(NetconfException::class) + fun checkAndReestablish() + + /** + * Get the device information for initialised session. + * + * @return DeviceInfo as device information + */ + fun getDeviceInfo(): DeviceInfo + + /** + * Gets the session ID of the Netconf session. + * + * @return Session ID as a string. + */ + fun getSessionId(): String + + /** + * Gets the capabilities of the remote Netconf device associated to this session. + * + * @return Network capabilities as strings in a Set. + */ + fun getDeviceCapabilitiesSet(): Set +} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/NetconfSessionListener.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/NetconfSessionListener.kt new file mode 100644 index 000000000..cfdd0104c --- /dev/null +++ b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/NetconfSessionListener.kt @@ -0,0 +1,21 @@ +/* + * Copyright © 2017-2019 AT&T, Bell Canada + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api + +interface NetconfSessionListener { + + fun notify(event: NetconfReceivedEvent) +} diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfDeviceCommunicator.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfDeviceCommunicator.kt new file mode 100644 index 000000000..4199998a8 --- /dev/null +++ b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfDeviceCommunicator.kt @@ -0,0 +1,243 @@ +/* + * Copyright © 2017-2019 AT&T, Bell Canada + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.core + +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.DeviceInfo +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.NetconfReceivedEvent +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.NetconfSessionListener +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.utils.NetconfMessageUtils +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.utils.RpcMessageUtils +import org.slf4j.LoggerFactory +import java.io.BufferedReader +import java.io.IOException +import java.io.InputStream +import java.io.InputStreamReader +import java.io.OutputStream +import java.io.OutputStreamWriter +import java.nio.charset.StandardCharsets +import java.util.concurrent.CompletableFuture + +class NetconfDeviceCommunicator(private var inputStream: InputStream, + private var out: OutputStream, + private val deviceInfo: DeviceInfo, + private val sessionListener: NetconfSessionListener, + private var replies: MutableMap>) : Thread() { + + private val log = LoggerFactory.getLogger(NetconfDeviceCommunicator::class.java) + private var state = NetconfMessageState.NO_MATCHING_PATTERN + + init { + start() + } + + override fun run() { + var bufferReader: BufferedReader? = null + while (bufferReader == null) { + bufferReader = BufferedReader(InputStreamReader(inputStream, StandardCharsets.UTF_8)) + } + + try { + var socketClosed = false + val deviceReplyBuilder = StringBuilder() + while (!socketClosed) { + val cInt = bufferReader.read() + if (cInt == -1) { + log.error("$deviceInfo: Received cInt = -1") +// bufferReader.close() + socketClosed = true +// sessionListener.notify(NetconfReceivedEvent( +// NetconfReceivedEvent.Type.SESSION_CLOSED, +// deviceInfo = deviceInfo)) + } + val c = cInt.toChar() + state = state.evaluateChar(c) + deviceReplyBuilder.append(c) + if (state === NetconfMessageState.END_PATTERN) { + var deviceReply = deviceReplyBuilder.toString() + if (deviceReply == RpcMessageUtils.END_PATTERN) { + socketClosed = true + bufferReader.close() + sessionListener.notify(NetconfReceivedEvent( + NetconfReceivedEvent.Type.DEVICE_UNREGISTERED, + deviceInfo = deviceInfo)) + } else { + deviceReply = deviceReply.replace(RpcMessageUtils.END_PATTERN, "") + receivedMessage(deviceReply) + deviceReplyBuilder.setLength(0) + } + } else if (state === NetconfMessageState.END_CHUNKED_PATTERN) { + var deviceReply = deviceReplyBuilder.toString() + if (!NetconfMessageUtils.validateChunkedFraming(deviceReply)) { + log.debug("$deviceInfo: Received badly framed message $deviceReply") + socketClosed = true + sessionListener.notify(NetconfReceivedEvent( + NetconfReceivedEvent.Type.DEVICE_ERROR, + deviceInfo = deviceInfo)) + } else { + deviceReply = deviceReply.replace(RpcMessageUtils.MSGLEN_REGEX_PATTERN.toRegex(), "") + deviceReply = deviceReply.replace(NetconfMessageUtils.CHUNKED_END_REGEX_PATTERN.toRegex(), "") + receivedMessage(deviceReply) + deviceReplyBuilder.setLength(0) + } + } + } + + } catch (e: IOException) { + log.warn("$deviceInfo: Fail while reading from channel", e) + sessionListener.notify(NetconfReceivedEvent( + NetconfReceivedEvent.Type.DEVICE_ERROR, + deviceInfo = deviceInfo)) + } + + } + + private enum class NetconfMessageState { + NO_MATCHING_PATTERN { + override fun evaluateChar(c: Char): NetconfMessageState { + return if (c == ']') { + FIRST_BRACKET + } else if (c == '\n') { + FIRST_LF + } else { + this + } + } + }, + FIRST_BRACKET { + override fun evaluateChar(c: Char): NetconfMessageState { + return if (c == ']') { + SECOND_BRACKET + } else { + NO_MATCHING_PATTERN + } + } + }, + SECOND_BRACKET { + override fun evaluateChar(c: Char): NetconfMessageState { + return if (c == '>') { + FIRST_BIGGER + } else { + NO_MATCHING_PATTERN + } + } + }, + FIRST_BIGGER { + override fun evaluateChar(c: Char): NetconfMessageState { + return if (c == ']') { + THIRD_BRACKET + } else { + NO_MATCHING_PATTERN + } + } + }, + THIRD_BRACKET { + override fun evaluateChar(c: Char): NetconfMessageState { + return if (c == ']') { + ENDING_BIGGER + } else { + NO_MATCHING_PATTERN + } + } + }, + ENDING_BIGGER { + override fun evaluateChar(c: Char): NetconfMessageState { + return if (c == '>') { + END_PATTERN + } else { + NO_MATCHING_PATTERN + } + } + }, + FIRST_LF { + override fun evaluateChar(c: Char): NetconfMessageState { + return if (c == '#') { + FIRST_HASH + } else if (c == ']') { + FIRST_BRACKET + } else if (c == '\n') { + this + } else { + NO_MATCHING_PATTERN + } + } + }, + FIRST_HASH { + override fun evaluateChar(c: Char): NetconfMessageState { + return if (c == '#') { + SECOND_HASH + } else { + NO_MATCHING_PATTERN + } + } + }, + SECOND_HASH { + override fun evaluateChar(c: Char): NetconfMessageState { + return if (c == '\n') { + END_CHUNKED_PATTERN + } else { + NO_MATCHING_PATTERN + } + } + }, + END_CHUNKED_PATTERN { + override fun evaluateChar(c: Char): NetconfMessageState { + return NO_MATCHING_PATTERN + } + }, + END_PATTERN { + override fun evaluateChar(c: Char): NetconfMessageState { + return NO_MATCHING_PATTERN + } + }; + + internal abstract fun evaluateChar(c: Char): NetconfMessageState + } + + fun sendMessage(request: String, messageId: String): CompletableFuture { + log.info("$deviceInfo: Sending message: \n $request") + val future = CompletableFuture() + replies.put(messageId, future) + val outputStream = OutputStreamWriter(out, StandardCharsets.UTF_8) + synchronized(this) { + try { + outputStream.write(request) + outputStream.flush() + } catch (e: IOException) { + log.error("$deviceInfo: Failed to send message : \n $request", e) + future.completeExceptionally(e) + } + + } + return future + } + + private fun receivedMessage(deviceReply: String) { + if (deviceReply.contains(RpcMessageUtils.RPC_REPLY) || deviceReply.contains(RpcMessageUtils.RPC_ERROR) + || deviceReply.contains(RpcMessageUtils.HELLO)) { + log.info("$deviceInfo: Received message with messageId: {} \n $deviceReply", + NetconfMessageUtils.getMsgId(deviceReply)) + + } else { + log.error("$deviceInfo: Invalid message received: \n $deviceReply") + } + sessionListener.notify(NetconfReceivedEvent( + NetconfReceivedEvent.Type.DEVICE_REPLY, + deviceReply, + NetconfMessageUtils.getMsgId(deviceReply), + deviceInfo)) + } +} diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfRpcServiceImpl.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfRpcServiceImpl.kt new file mode 100644 index 000000000..4619460e3 --- /dev/null +++ b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfRpcServiceImpl.kt @@ -0,0 +1,220 @@ +/* + * Copyright © 2017-2019 AT&T, Bell Canada + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.core + +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.DeviceInfo +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.DeviceResponse +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.NetconfException +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.NetconfRpcService +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.NetconfSession +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.utils.NetconfMessageUtils +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.utils.RpcStatus +import org.slf4j.LoggerFactory +import java.util.concurrent.TimeUnit +import java.util.concurrent.atomic.AtomicInteger + +class NetconfRpcServiceImpl(private var deviceInfo: DeviceInfo) : NetconfRpcService { + + private val log = LoggerFactory.getLogger(NetconfRpcService::class.java) + + private var responseTimeout: Int = deviceInfo.replyTimeout + + private lateinit var netconfSession: NetconfSession + + private val messageIdInteger = AtomicInteger(1) + + fun setNetconfSession(netconfSession: NetconfSession) { + this.netconfSession = netconfSession + } + + override fun invokeRpc(rpc: String): DeviceResponse { + var output = DeviceResponse() + val messageId = messageIdInteger.getAndIncrement().toString() + log.info("$deviceInfo: invokeRpc: messageId($messageId)") + try { + output = asyncRpc(rpc, messageId) + } catch (e: Exception) { + output.status = RpcStatus.FAILURE + output.errorMessage = "$deviceInfo: failed in invokeRpc command $e.message" + } + return output + } + + override fun getConfig(filter: String, configTarget: String): DeviceResponse { + var output = DeviceResponse() + val messageId = messageIdInteger.getAndIncrement().toString() + log.info("$deviceInfo: getConfig: messageId($messageId)") + try { + val message = NetconfMessageUtils.getConfig(messageId, configTarget, filter) + output = asyncRpc(message, messageId) + } catch (e: Exception) { + output.status = RpcStatus.FAILURE + output.errorMessage = "$deviceInfo: failed in get-config command $e.message" + } + return output + } + + override fun deleteConfig(configTarget: String): DeviceResponse { + var output = DeviceResponse() + val messageId = messageIdInteger.getAndIncrement().toString() + log.info("$deviceInfo: deleteConfig: messageId($messageId)") + try { + val deleteConfigMessage = NetconfMessageUtils.deleteConfig(messageId, configTarget) + output.requestMessage = deleteConfigMessage + output = asyncRpc(deleteConfigMessage, messageId) + } catch (e: Exception) { + output.status = RpcStatus.FAILURE + output.errorMessage = "$deviceInfo: failed in delete config command $e.message" + } + return output + } + + override fun lock(configTarget: String): DeviceResponse { + var output = DeviceResponse() + val messageId = messageIdInteger.getAndIncrement().toString() + log.info("$deviceInfo: lock: messageId($messageId)") + try { + val lockMessage = NetconfMessageUtils.lock(messageId, configTarget) + output.requestMessage = lockMessage + output = asyncRpc(lockMessage, messageId) + } catch (e: Exception) { + output.status = RpcStatus.FAILURE + output.errorMessage = "$deviceInfo: failed in lock command $e.message" + } + + return output + } + + override fun unLock(configTarget: String): DeviceResponse { + var output = DeviceResponse() + val messageId = messageIdInteger.getAndIncrement().toString() + log.info("$deviceInfo: unLock: messageId($messageId)") + try { + val unlockMessage = NetconfMessageUtils.unlock(messageId, configTarget) + output.requestMessage = unlockMessage + output = asyncRpc(unlockMessage, messageId) + } catch (e: Exception) { + output.status = RpcStatus.FAILURE + output.errorMessage = "$deviceInfo: failed in lock command $e.message" + } + return output + } + + override fun commit(confirmed: Boolean, confirmTimeout: Int, persist: String, persistId: String): DeviceResponse { + var output = DeviceResponse() + val messageId = messageIdInteger.getAndIncrement().toString() + log.info("$deviceInfo: commit: messageId($messageId)") + try { + val messageContent = NetconfMessageUtils.commit(messageId, confirmed, confirmTimeout, persist, persistId) + output = asyncRpc(messageContent, messageId) + } catch (e: Exception) { + output.status = RpcStatus.FAILURE + output.errorMessage = "$deviceInfo: failed in commit command $e.message" + } + return output + } + + override fun cancelCommit(persistId: String): DeviceResponse { + var output = DeviceResponse() + val messageId = messageIdInteger.getAndIncrement().toString() + log.info("$deviceInfo: cancelCommit: messageId($messageId)") + try { + val messageContent = NetconfMessageUtils.cancelCommit(messageId, persistId) + output = asyncRpc(messageContent, messageId) + } catch (e: Exception) { + output.status = RpcStatus.FAILURE + output.errorMessage = "$deviceInfo: failed in cancelCommit command $e.message" + } + return output + } + + override fun discardConfig(): DeviceResponse { + var output = DeviceResponse() + val messageId = messageIdInteger.getAndIncrement().toString() + log.info("$deviceInfo: discard: messageId($messageId)") + try { + val discardChangesMessage = NetconfMessageUtils.discardChanges(messageId) + output.requestMessage = discardChangesMessage + output = asyncRpc(discardChangesMessage, messageId) + } catch (e: Exception) { + output.status = RpcStatus.FAILURE + output.errorMessage = "$deviceInfo: failed in discard changes command " + e.message + } + return output + } + + override fun editConfig(messageContent: String, configTarget: String, + editDefaultOperation: String): DeviceResponse { + var response = DeviceResponse() + val messageId = messageIdInteger.getAndIncrement().toString() + log.info("$deviceInfo: editConfig: messageId($messageId)") + try { + val editMessage = + NetconfMessageUtils.editConfig(messageId, configTarget, editDefaultOperation, messageContent) + response.requestMessage = editMessage + response = asyncRpc(editMessage, messageId) + } catch (e: Exception) { + response.status = RpcStatus.FAILURE + response.errorMessage = e.message + } + return response + } + + override fun validate(configTarget: String): DeviceResponse { + var output = DeviceResponse() + val messageId = messageIdInteger.getAndIncrement().toString() + try { + val validateMessage = NetconfMessageUtils.validate(messageId, configTarget) + output.requestMessage = validateMessage + output = asyncRpc(validateMessage, messageId) + } catch (e: Exception) { + output.status = RpcStatus.FAILURE + output.errorMessage = "$deviceInfo: failed in validate command " + e.message + } + return output + } + + override fun closeSession(force: Boolean): DeviceResponse { + var output = DeviceResponse() + val messageId = messageIdInteger.getAndIncrement().toString() + log.info("$deviceInfo: closeSession: messageId($messageId)") + try { + val messageContent = NetconfMessageUtils.closeSession(messageId, force) + output = asyncRpc(messageContent, messageId) + } catch (e: Exception) { + output.status = RpcStatus.FAILURE + output.errorMessage = "$deviceInfo: failed in closeSession command " + e.message + } + return output + } + + @Throws(NetconfException::class) + override fun asyncRpc(request: String, messageId: String): DeviceResponse { + val response = DeviceResponse() + log.info("$deviceInfo: send asyncRpc with messageId($messageId)") + response.requestMessage = request + + val rpcResponse = netconfSession.asyncRpc(request, messageId).get(responseTimeout.toLong(), TimeUnit.SECONDS) + if (!NetconfMessageUtils.checkReply(rpcResponse)) { + throw NetconfException(rpcResponse) + } + response.responseMessage = rpcResponse + response.status = RpcStatus.SUCCESS + response.errorMessage = null + return response + } +} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfSessionImpl.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfSessionImpl.kt new file mode 100644 index 000000000..d1ecb4f75 --- /dev/null +++ b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfSessionImpl.kt @@ -0,0 +1,287 @@ +/* + * Copyright © 2017-2019 AT&T, Bell Canada + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.core + +import com.google.common.collect.ImmutableList +import com.google.common.collect.ImmutableSet +import org.apache.sshd.client.SshClient +import org.apache.sshd.client.channel.ChannelSubsystem +import org.apache.sshd.client.channel.ClientChannel +import org.apache.sshd.client.session.ClientSession +import org.apache.sshd.client.session.ClientSessionImpl +import org.apache.sshd.common.FactoryManager +import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.DeviceInfo +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.NetconfException +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.NetconfReceivedEvent +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.NetconfRpcService +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.NetconfSession +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.NetconfSessionListener +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.utils.NetconfMessageUtils +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.utils.RpcMessageUtils +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.utils.RpcStatus +import org.slf4j.LoggerFactory +import java.io.IOException +import java.util.* +import java.util.concurrent.CompletableFuture +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.ExecutionException +import java.util.concurrent.TimeUnit +import java.util.concurrent.TimeoutException +import java.util.concurrent.atomic.AtomicReference + +class NetconfSessionImpl(private val deviceInfo: DeviceInfo, private val rpcService: NetconfRpcService) : + NetconfSession { + + private val log = LoggerFactory.getLogger(NetconfSessionImpl::class.java) + + private val errorReplies: MutableList = Collections.synchronizedList(listOf()) + private val replies: MutableMap> = ConcurrentHashMap() + private val deviceCapabilities = setOf() + + private var connectionTimeout: Long = 0 + private var replyTimeout: Int = 0 + private var idleTimeout: Int = 0 + private var sessionId: String? = null + + private lateinit var session: ClientSession + private lateinit var client: SshClient + private lateinit var channel: ClientChannel + private lateinit var streamHandler: NetconfDeviceCommunicator + + private var capabilities = + ImmutableList.of(RpcMessageUtils.NETCONF_10_CAPABILITY, RpcMessageUtils.NETCONF_11_CAPABILITY) + + override fun connect() { + try { + log.info("$deviceInfo: Connecting to Netconf Device with timeouts C:${deviceInfo.connectTimeout}, " + + "R:${deviceInfo.replyTimeout}, I:${deviceInfo.idleTimeout}") + startConnection() + log.info("$deviceInfo: Connected to Netconf Device") + } catch (e: NetconfException) { + log.error("$deviceInfo: Netconf Device Connection Failed. ${e.message}") + throw NetconfException(e) + } + } + + override fun disconnect() { + if (rpcService.closeSession(false).status.equals( + RpcStatus.FAILURE, true)) { + rpcService.closeSession(true) + } + + session.close() + // Closes the socket which should interrupt the streamHandler + channel.close() + client.close() + } + + override fun reconnect() { + disconnect() + connect() + } + + override fun syncRpc(request: String, messageId: String): String { + val formattedRequest = NetconfMessageUtils.formatRPCRequest(request, messageId, deviceCapabilities) + + checkAndReestablish() + + try { + return streamHandler.sendMessage(formattedRequest, messageId).get(replyTimeout.toLong(), TimeUnit.SECONDS) +// replies.remove(messageId) + } catch (e: InterruptedException) { + Thread.currentThread().interrupt() + throw NetconfException("$deviceInfo: Interrupted while waiting for reply for request: $formattedRequest", e) + } catch (e: TimeoutException) { + throw NetconfException("$deviceInfo: Timed out while waiting for reply for request $formattedRequest after $replyTimeout sec.", + e) + } catch (e: ExecutionException) { + log.warn("$deviceInfo: Closing session($sessionId) due to unexpected Error", e) + try { + session.close() + // Closes the socket which should interrupt the streamHandler + channel.close() + client.close() + } catch (ioe: IOException) { + log.warn("$deviceInfo: Error closing session($sessionId) for host($deviceInfo)", ioe) + } + +// NetconfReceivedEvent(NetconfReceivedEvent.Type.SESSION_CLOSED, "", +// "Closed due to unexpected error " + e.cause, "-1", deviceInfo) + errorReplies.clear() // move to cleanUp()? + replies.clear() + + throw NetconfException("$deviceInfo: Closing session $sessionId for request $formattedRequest", e) + } + } + + override fun asyncRpc(request: String, messageId: String): CompletableFuture { + val formattedRequest = NetconfMessageUtils.formatRPCRequest(request, messageId, deviceCapabilities) + + checkAndReestablish() + + return streamHandler.sendMessage(formattedRequest, messageId).handleAsync { reply, t -> + if (t != null) { + throw NetconfException(messageId, t) + } + reply + } + } + + override fun checkAndReestablish() { + try { + if (client.isClosed) { + log.info("Trying to restart the whole SSH connection with {}", deviceInfo) + replies.clear() + startConnection() + } else if (session.isClosed) { + log.info("Trying to restart the session with {}", deviceInfo) + replies.clear() + startSession() + } else if (channel.isClosed) { + log.info("Trying to reopen the channel with {}", deviceInfo) + replies.clear() + openChannel() + } else { + return + } + } catch (e: IOException) { + log.error("Can't reopen connection for device {}", e.message) + throw NetconfException(String.format("Cannot re-open the connection with device (%s)", deviceInfo), e) + } catch (e: IllegalStateException) { + log.error("Can't reopen connection for device {}", e.message) + throw NetconfException(String.format("Cannot re-open the connection with device (%s)", deviceInfo), e) + } + + } + + override fun getDeviceInfo(): DeviceInfo { + return deviceInfo + } + + override fun getSessionId(): String { + return this.sessionId!! + } + + override fun getDeviceCapabilitiesSet(): Set { + return Collections.unmodifiableSet(deviceCapabilities) + } + + private fun startConnection() { + connectionTimeout = deviceInfo.connectTimeout + replyTimeout = deviceInfo.replyTimeout + idleTimeout = deviceInfo.idleTimeout + try { + startClient() + } catch (e: Exception) { + throw NetconfException("$deviceInfo: Failed to establish SSH session", e) + } + + } + + private fun startClient() { + client = SshClient.setUpDefaultClient() + client.properties.putIfAbsent(FactoryManager.IDLE_TIMEOUT, TimeUnit.SECONDS.toMillis(idleTimeout.toLong())) + client.properties.putIfAbsent(FactoryManager.NIO2_READ_TIMEOUT, TimeUnit.SECONDS.toMillis(idleTimeout + 15L)) + client.keyPairProvider = SimpleGeneratorHostKeyProvider() + client.start() + + startSession() + } + + private fun startSession() { + log.info("$deviceInfo: Starting SSH session") + val connectFuture = client.connect(deviceInfo.username, deviceInfo.ipAddress, deviceInfo.port) + .verify(connectionTimeout, TimeUnit.SECONDS) + session = connectFuture.session + log.info("$deviceInfo: SSH session created") + + authSession() + } + + private fun authSession() { + session.addPasswordIdentity(deviceInfo.password) + session.auth().verify(connectionTimeout, TimeUnit.SECONDS) + val event = session.waitFor(ImmutableSet.of(ClientSession.ClientSessionEvent.WAIT_AUTH, + ClientSession.ClientSessionEvent.CLOSED, ClientSession.ClientSessionEvent.AUTHED), 0) + if (!event.contains(ClientSession.ClientSessionEvent.AUTHED)) { + throw NetconfException("$deviceInfo: Failed to authenticate session.") + } + log.info("$deviceInfo: SSH session authenticated") + + openChannel() + } + + private fun openChannel() { + channel = session.createSubsystemChannel("netconf") + val channelFuture = channel.open() + if (channelFuture.await(connectionTimeout, TimeUnit.SECONDS) && channelFuture.isOpened) { + log.info("$deviceInfo: SSH NETCONF subsystem channel opened") + setupHandler() + } else { + throw NetconfException("$deviceInfo: Failed to open SSH subsystem channel") + } + } + + private fun setupHandler() { + val sessionListener: NetconfSessionListener = NetconfSessionListenerImpl() + streamHandler = NetconfDeviceCommunicator(channel.invertedOut, channel.invertedIn, deviceInfo, + sessionListener, replies) + + exchangeHelloMessage() + } + + private fun exchangeHelloMessage() { + sessionId = "-1" + val messageId = "-1" + + val serverHelloResponse = syncRpc(NetconfMessageUtils.createHelloString(capabilities), messageId) + val sessionIDMatcher = NetconfMessageUtils.SESSION_ID_REGEX_PATTERN.matcher(serverHelloResponse) + + if (sessionIDMatcher.find()) { + sessionId = sessionIDMatcher.group(1) + } else { + throw NetconfException("$deviceInfo: Missing sessionId in server hello message: $serverHelloResponse") + } + + val capabilityMatcher = NetconfMessageUtils.CAPABILITY_REGEX_PATTERN.matcher(serverHelloResponse) + while (capabilityMatcher.find()) { + deviceCapabilities.plus(capabilityMatcher.group(1)) + } + } + + inner class NetconfSessionListenerImpl : NetconfSessionListener { + override fun notify(event: NetconfReceivedEvent) { + val messageId = event.getMessageID() + + when (event.getType()) { + NetconfReceivedEvent.Type.DEVICE_UNREGISTERED -> disconnect() + NetconfReceivedEvent.Type.DEVICE_ERROR -> errorReplies.add(event.getMessagePayload()) + NetconfReceivedEvent.Type.DEVICE_REPLY -> replies[messageId]?.complete(event.getMessagePayload()) + NetconfReceivedEvent.Type.SESSION_CLOSED -> disconnect() + } + } + } + + fun sessionstatus(state:String): Boolean{ + return when (state){ + "Close" -> channel.isClosed + "Open" -> channel.isOpen + else -> false + } + } +} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/utils/NetconfConstant.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/utils/NetconfConstant.kt new file mode 100644 index 000000000..8722bb031 --- /dev/null +++ b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/utils/NetconfConstant.kt @@ -0,0 +1,90 @@ +/* + * Copyright © 2017-2019 AT&T, Bell Canada + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.utils + +enum class NetconfDatastore(val datastore: String) { + RUNNING("running"), + CANDIDATE("candidate"); +} + +enum class ModifyAction(val action: String) { + MERGE("merge"), + REPLACE("replace"), + NONE("none") +} + +object RpcStatus { + const val SUCCESS = "success" + const val FAILURE = "failure" +} + +object RpcMessageUtils { + const val OPEN = "<" + const val CLOSE = ">" + const val EQUAL = "=" + + const val HASH = "#" + const val HASH_CHAR = '#' + + const val LF_CHAR = '\n' + const val NEW_LINE = "\n" + + const val QUOTE = "\"" + const val QUOTE_SPACE = "\" " + + const val TAG_CLOSE = "/>" + const val END_OF_RPC_OPEN_TAG = "\">" + const val END_PATTERN = "]]>]]>" + + const val HELLO = "hello" + const val RPC_REPLY = "rpc-reply" + const val RPC_ERROR = "rpc-error" + + const val RPC_OPEN = "" + const val SUBTREE_FILTER_CLOSE = "" + const val TARGET_OPEN = "" + const val TARGET_CLOSE = "" + const val SOURCE_OPEN = "" + const val SOURCE_CLOSE = "" + const val CONFIG_OPEN = "" + const val CONFIG_CLOSE = "" + const val MSGLEN_REGEX_PATTERN = "\n#\\d+\n" + + const val NUMBER_BETWEEN_QUOTES_MATCHER = "\"+([0-9]+)+\"" + + const val XML_HEADER = "" + const val NETCONF_BASE_NAMESPACE = "xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"" + const val NETCONF_WITH_DEFAULTS_NAMESPACE = "xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\"" + const val SUBSCRIPTION_SUBTREE_FILTER_OPEN = + "" + + const val INTERLEAVE_CAPABILITY_STRING = "urn:ietf:params:netconf:capability:interleave:1.0" + + const val CAPABILITY_REGEX = "capability>\\s*(.*?)\\s*capability>" + + const val SESSION_ID_REGEX = "session-id>\\s*(.*?)\\s*session-id>" + + const val MESSAGE_ID_STRING = "message-id" + + const val NETCONF_10_CAPABILITY = "urn:ietf:params:netconf:base:1.0" + const val NETCONF_11_CAPABILITY = "urn:ietf:params:netconf:base:1.1" +} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/utils/NetconfMessageUtils.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/utils/NetconfMessageUtils.kt new file mode 100644 index 000000000..1ffc9a68c --- /dev/null +++ b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/utils/NetconfMessageUtils.kt @@ -0,0 +1,404 @@ +/* + * Copyright © 2017-2019 AT&T, Bell Canada + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.utils + +import org.apache.commons.lang3.StringUtils +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.NetconfException +import org.slf4j.LoggerFactory +import org.xml.sax.InputSource +import java.io.StringReader +import java.nio.charset.StandardCharsets +import java.util.regex.MatchResult +import java.util.regex.Pattern +import javax.xml.XMLConstants +import javax.xml.parsers.DocumentBuilderFactory +import kotlin.text.Charsets.UTF_8 + + +class NetconfMessageUtils { + + companion object { + val log = LoggerFactory.getLogger(NetconfMessageUtils::class.java) + + const val NEW_LINE = "\n" + const val CHUNKED_END_REGEX_PATTERN = "\n##\n" + + val CAPABILITY_REGEX_PATTERN: Pattern = Pattern.compile(RpcMessageUtils.CAPABILITY_REGEX) + val SESSION_ID_REGEX_PATTERN: Pattern = Pattern.compile(RpcMessageUtils.SESSION_ID_REGEX) + + private val CHUNKED_FRAMING_PATTERN: Pattern = + Pattern.compile("(\\n#([1-9][0-9]*)\\n(.+))+\\n##\\n", Pattern.DOTALL) + private val CHUNKED_SIZE_PATTERN: Pattern = Pattern.compile("\\n#([1-9][0-9]*)\\n") + private val MSG_ID_STRING_PATTERN = Pattern.compile("${RpcMessageUtils.MESSAGE_ID_STRING}=\"(.*?)\"") + + fun getConfig(messageId: String, configType: String, filterContent: String?): String { + val request = StringBuilder() + + request.append("").append(NEW_LINE) + request.append(RpcMessageUtils.SOURCE_OPEN).append(NEW_LINE) + request.append(RpcMessageUtils.OPEN).append(configType).append(RpcMessageUtils.TAG_CLOSE) + .append(NEW_LINE) + request.append(RpcMessageUtils.SOURCE_CLOSE).append(NEW_LINE) + + if (!filterContent.isNullOrEmpty()) { + request.append(RpcMessageUtils.SUBTREE_FILTER_OPEN).append(NEW_LINE) + request.append(filterContent).append(NEW_LINE) + request.append(RpcMessageUtils.SUBTREE_FILTER_CLOSE).append(NEW_LINE) + } + request.append("").append(NEW_LINE) + + return doWrappedRpc(messageId, request.toString()) + } + + fun doWrappedRpc(messageId: String, request: String): String { + val rpc = StringBuilder(RpcMessageUtils.XML_HEADER).append(NEW_LINE) + rpc.append(RpcMessageUtils.RPC_OPEN) + rpc.append(RpcMessageUtils.MESSAGE_ID_STRING).append(RpcMessageUtils.EQUAL) + rpc.append(RpcMessageUtils.QUOTE).append(messageId).append(RpcMessageUtils.QUOTE_SPACE) + rpc.append(RpcMessageUtils.NETCONF_BASE_NAMESPACE).append(RpcMessageUtils.CLOSE) + .append(NEW_LINE) + rpc.append(request) + rpc.append(RpcMessageUtils.RPC_CLOSE) + // rpc.append(NEW_LINE).append(END_PATTERN); + + return rpc.toString() + } + + fun editConfig(messageId: String, configType: String, defaultOperation: String?, + newConfiguration: String): String { + + val request = StringBuilder() + + request.append("").append(NEW_LINE) + request.append(RpcMessageUtils.TARGET_OPEN).append(NEW_LINE) + request.append(RpcMessageUtils.OPEN).append(configType).append(RpcMessageUtils.TAG_CLOSE) + .append(NEW_LINE) + request.append(RpcMessageUtils.TARGET_CLOSE).append(NEW_LINE) + + if (defaultOperation != null) { + request.append(RpcMessageUtils.DEFAULT_OPERATION_OPEN).append(defaultOperation) + .append(RpcMessageUtils.DEFAULT_OPERATION_CLOSE) + request.append(NEW_LINE) + } + + request.append(RpcMessageUtils.CONFIG_OPEN).append(NEW_LINE) + request.append(newConfiguration.trim { it <= ' ' }).append(NEW_LINE) + request.append(RpcMessageUtils.CONFIG_CLOSE).append(NEW_LINE) + request.append("").append(NEW_LINE) + + return doWrappedRpc(messageId, request.toString()) + } + + fun validate(messageId: String, configType: String): String { + val request = StringBuilder() + + request.append("").append(NEW_LINE) + request.append(RpcMessageUtils.SOURCE_OPEN).append(NEW_LINE) + request.append(RpcMessageUtils.OPEN).append(configType).append(RpcMessageUtils.TAG_CLOSE) + .append(NEW_LINE) + request.append(RpcMessageUtils.SOURCE_CLOSE).append(NEW_LINE) + request.append("").append(NEW_LINE) + + return doWrappedRpc(messageId, request.toString()) + } + + fun commit(messageId: String, confirmed: Boolean, confirmTimeout: Int, persist: String, + persistId: String): String { + + if (!persist.isEmpty() && !persistId.isEmpty()) { + throw NetconfException("Can't proceed with both persist($persist) and " + + "persistId($persistId) specified. Only one should be specified.") + } + if (confirmed && !persistId.isEmpty()) { + throw NetconfException("Can't proceed with both confirmed flag and " + + "persistId($persistId) specified. Only one should be specified.") + } + + val request = StringBuilder() + request.append("").append(NEW_LINE) + if (confirmed) { + request.append("") + request.append("$confirmTimeout") + if (!persist.isEmpty()) { + request.append("$persist") + } + } + if (!persistId.isEmpty()) { + request.append("$persistId") + } + request.append("").append(NEW_LINE) + + return doWrappedRpc(messageId, request.toString()) + } + + fun cancelCommit(messageId: String, persistId: String): String { + val request = StringBuilder() + request.append("").append(NEW_LINE) + if (!persistId.isEmpty()) { + request.append("$persistId") + } + request.append("").append(NEW_LINE) + + return doWrappedRpc(messageId, request.toString()) + } + + fun unlock(messageId: String, configType: String): String { + val request = StringBuilder() + + request.append("").append(NEW_LINE) + request.append(RpcMessageUtils.TARGET_OPEN).append(NEW_LINE) + request.append(RpcMessageUtils.OPEN).append(configType).append(RpcMessageUtils.TAG_CLOSE) + .append(NEW_LINE) + request.append(RpcMessageUtils.TARGET_CLOSE).append(NEW_LINE) + request.append("").append(NEW_LINE) + + return doWrappedRpc(messageId, request.toString()) + } + + @Throws(NetconfException::class) + fun deleteConfig(messageId: String, configType: String): String { + if (configType == NetconfDatastore.RUNNING.datastore) { + log.warn("Target configuration for delete operation can't be \"running\" {}", configType) + throw NetconfException("Target configuration for delete operation can't be running") + } + + val request = StringBuilder() + + request.append("").append(NEW_LINE) + request.append(RpcMessageUtils.TARGET_OPEN).append(NEW_LINE) + request.append(RpcMessageUtils.OPEN).append(configType) + .append(RpcMessageUtils.TAG_CLOSE) + .append(NEW_LINE) + request.append(RpcMessageUtils.TARGET_CLOSE).append(NEW_LINE) + request.append("").append(NEW_LINE) + + return doWrappedRpc(messageId, request.toString()) + } + + fun discardChanges(messageId: String): String { + val request = StringBuilder() + request.append("").append(NEW_LINE) + return doWrappedRpc(messageId, request.toString()) + } + + fun lock(messageId: String, configType: String): String { + val request = StringBuilder() + + request.append("").append(NEW_LINE) + request.append(RpcMessageUtils.TARGET_OPEN).append(NEW_LINE) + request.append(RpcMessageUtils.OPEN).append(configType).append(RpcMessageUtils.TAG_CLOSE) + .append(NEW_LINE) + request.append(RpcMessageUtils.TARGET_CLOSE).append(NEW_LINE) + request.append("").append(NEW_LINE) + + return doWrappedRpc(messageId, request.toString()) + } + + fun closeSession(messageId: String, force: Boolean): String { + val request = StringBuilder() + + if (force) { + request.append("").append(NEW_LINE) + } else { + request.append("").append(NEW_LINE) + } + + return doWrappedRpc(messageId, request.toString()) + } + + fun validateRPCXML(rpcRequest: String): Boolean { + try { + if (StringUtils.isBlank(rpcRequest)) { + return false + } + val dbf = DocumentBuilderFactory.newInstance() + dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true) + dbf.setFeature("http://xml.org/sax/features/external-general-entities", false) + dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false) + dbf.newDocumentBuilder() + .parse(InputSource(StringReader(rpcRequest.replace(RpcMessageUtils.END_PATTERN, "")))) + return true + } catch (e: Exception) { + return false + } + + } + + fun getMsgId(message: String): String { + val matcher = MSG_ID_STRING_PATTERN.matcher(message) + if (matcher.find()) { + return matcher.group(1) + } + return if (message.contains(RpcMessageUtils.HELLO)) { + (-1).toString() + } else "" + } + + fun validateChunkedFraming(reply: String): Boolean { + val matcher = CHUNKED_FRAMING_PATTERN.matcher(reply) + if (!matcher.matches()) { + log.debug("Error Reply: {}", reply) + return false + } + val chunkM = CHUNKED_SIZE_PATTERN.matcher(reply) + val chunks = ArrayList() + var chunkdataStr = "" + while (chunkM.find()) { + chunks.add(chunkM.toMatchResult()) + // extract chunk-data (and later) in bytes + val bytes = Integer.parseInt(chunkM.group(1)) + val chunkdata = reply.substring(chunkM.end()).toByteArray(StandardCharsets.UTF_8) + if (bytes > chunkdata.size) { + log.debug("Error Reply - wrong chunk size {}", reply) + return false + } + // convert (only) chunk-data part into String + chunkdataStr = String(chunkdata, 0, bytes, StandardCharsets.UTF_8) + // skip chunk-data part from next match + chunkM.region(chunkM.end() + chunkdataStr.length, reply.length) + } + if (!CHUNKED_END_REGEX_PATTERN.equals(reply.substring(chunks[chunks.size - 1].end() + chunkdataStr.length))) { + log.debug("Error Reply: {}", reply) + return false + } + return true + } + + fun createHelloString(capabilities: List): String { + val helloMessage = StringBuilder() + helloMessage.append(RpcMessageUtils.XML_HEADER).append(NEW_LINE) + helloMessage.append("").append(NEW_LINE) + helloMessage.append(" ").append(NEW_LINE) + if (capabilities.isNotEmpty()) { + capabilities.forEach { cap -> + helloMessage.append(" ").append(cap).append("").append(NEW_LINE) + } + } + helloMessage.append(" ").append(NEW_LINE) + helloMessage.append("").append(NEW_LINE) + helloMessage.append(RpcMessageUtils.END_PATTERN) + return helloMessage.toString() + } + + fun formatRPCRequest(request: String, messageId: String, deviceCapabilities: Set): String { + var request = request + request = NetconfMessageUtils.formatNetconfMessage(deviceCapabilities, request) + request = NetconfMessageUtils.formatXmlHeader(request) + request = NetconfMessageUtils.formatRequestMessageId(request, messageId) + + return request + } + + /** + * Validate and format netconf message. - NC1.0 if no EOM sequence present on `message`, + * append. - NC1.1 chunk-encode given message unless it already is chunk encoded + * + * @param deviceCapabilities Set containing Device Capabilities + * @param message to format + * @return formated message + */ + fun formatNetconfMessage(deviceCapabilities: Set, message: String): String { + var message = message + if (deviceCapabilities.contains(RpcMessageUtils.NETCONF_11_CAPABILITY)) { + message = formatChunkedMessage(message) + } else if (!message.endsWith(RpcMessageUtils.END_PATTERN)) { + message = message + NEW_LINE + RpcMessageUtils.END_PATTERN + } + return message + } + + /** + * Validate and format message according to chunked framing mechanism. + * + * @param message to format + * @return formated message + */ + fun formatChunkedMessage(message: String): String { + var message = message + if (message.endsWith(RpcMessageUtils.END_PATTERN)) { + // message given had Netconf 1.0 EOM pattern -> remove + message = message.substring(0, message.length - RpcMessageUtils.END_PATTERN.length) + } + if (!message.startsWith(RpcMessageUtils.NEW_LINE + RpcMessageUtils.HASH)) { + // chunk encode message + message = + (RpcMessageUtils.NEW_LINE + RpcMessageUtils.HASH + message.toByteArray(UTF_8).size + RpcMessageUtils.NEW_LINE + message + RpcMessageUtils.NEW_LINE + RpcMessageUtils.HASH + RpcMessageUtils.HASH + + RpcMessageUtils.NEW_LINE) + } + return message + } + + /** + * Ensures xml start directive/declaration appears in the `request`. + * + * @param request RPC request message + * @return XML RPC message + */ + fun formatXmlHeader(request: String): String { + var request = request + if (!request.contains(RpcMessageUtils.XML_HEADER)) { + if (request.startsWith(RpcMessageUtils.NEW_LINE + RpcMessageUtils.HASH)) { + request = + request.split("<".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[0] + RpcMessageUtils.XML_HEADER + request.substring( + request.split("<".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[0].length) + } else { + request = RpcMessageUtils.XML_HEADER + "\n" + request + } + } + return request + } + + fun formatRequestMessageId(request: String, messageId: String): String { + var request = request + if (request.contains(RpcMessageUtils.MESSAGE_ID_STRING)) { + request = + request.replaceFirst((RpcMessageUtils.MESSAGE_ID_STRING + RpcMessageUtils.EQUAL + RpcMessageUtils.NUMBER_BETWEEN_QUOTES_MATCHER).toRegex(), + RpcMessageUtils.MESSAGE_ID_STRING + RpcMessageUtils.EQUAL + RpcMessageUtils.QUOTE + messageId + RpcMessageUtils.QUOTE) + } else if (!request.contains(RpcMessageUtils.MESSAGE_ID_STRING) && !request.contains( + RpcMessageUtils.HELLO)) { + request = request.replaceFirst(RpcMessageUtils.END_OF_RPC_OPEN_TAG.toRegex(), + RpcMessageUtils.QUOTE_SPACE + RpcMessageUtils.MESSAGE_ID_STRING + RpcMessageUtils.EQUAL + RpcMessageUtils.QUOTE + messageId + RpcMessageUtils.QUOTE + ">") + } + return updateRequestLength(request) + } + + fun updateRequestLength(request: String): String { + if (request.contains(NEW_LINE + RpcMessageUtils.HASH + RpcMessageUtils.HASH + NEW_LINE)) { + val oldLen = + Integer.parseInt(request.split(RpcMessageUtils.HASH.toRegex()).dropLastWhile({ it.isEmpty() }).toTypedArray()[1].split( + NEW_LINE.toRegex()).dropLastWhile({ it.isEmpty() }).toTypedArray()[0]) + val rpcWithEnding = request.substring(request.indexOf('<')) + val firstBlock = + request.split(RpcMessageUtils.MSGLEN_REGEX_PATTERN.toRegex()).dropLastWhile({ it.isEmpty() }).toTypedArray()[1].split( + (NEW_LINE + RpcMessageUtils.HASH + RpcMessageUtils.HASH + NEW_LINE).toRegex()).dropLastWhile( + { it.isEmpty() }).toTypedArray()[0] + var newLen = 0 + newLen = firstBlock.toByteArray(UTF_8).size + if (oldLen != newLen) { + return NEW_LINE + RpcMessageUtils.HASH + newLen + NEW_LINE + rpcWithEnding + } + } + return request + } + + fun checkReply(reply: String?): Boolean { + return if (reply != null) { + !reply.contains("rpc-error>") || reply.contains("warning") || reply.contains("ok/>") + } else false + } + } + +} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/ComponentNetconfExecutorTest.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/ComponentNetconfExecutorTest.kt deleted file mode 100644 index e2b901998..000000000 --- a/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/ComponentNetconfExecutorTest.kt +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright © 2017-2018 AT&T Intellectual Property. - * - * Modifications Copyright © 2019 IBM, Bell Canada. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor - -import com.fasterxml.jackson.databind.JsonNode -import org.junit.Test -import org.junit.runner.RunWith -import org.onap.ccsdk.apps.blueprintsprocessor.core.api.data.ExecutionServiceInput -import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintConstants -import org.onap.ccsdk.apps.controllerblueprints.core.asJsonNode -import org.onap.ccsdk.apps.controllerblueprints.core.putJsonElement -import org.onap.ccsdk.apps.controllerblueprints.core.utils.BluePrintMetadataUtils -import org.onap.ccsdk.apps.controllerblueprints.core.utils.JacksonUtils -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.autoconfigure.EnableAutoConfiguration -import org.springframework.context.annotation.ComponentScan -import org.springframework.test.annotation.DirtiesContext -import org.springframework.test.context.TestPropertySource -import org.springframework.test.context.junit4.SpringRunner - -@RunWith(SpringRunner::class) -@EnableAutoConfiguration -@ComponentScan(basePackages = ["org.onap.ccsdk.apps.blueprintsprocessor", "org.onap.ccsdk.apps.controllerblueprints"]) -@DirtiesContext -@TestPropertySource(properties = -["blueprints.processor.functions.python.executor.modulePaths=./../../../../components/scripts/python/ccsdk_netconf,./../../../../components/scripts/python/ccsdk_blueprints", - "blueprints.processor.functions.python.executor.executionPath=./../../../../components/scripts/python/ccsdk_netconf"], - locations = ["classpath:application-test.properties"]) -class ComponentNetconfExecutorTest { - - @Autowired - lateinit var componentNetconfExecutor: ComponentNetconfExecutor - - - @Test - fun testComponentNetconfExecutor() { - - val executionServiceInput = JacksonUtils.readValueFromClassPathFile("requests/sample-activate-request.json", - ExecutionServiceInput::class.java)!! - - val bluePrintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime("1234", - "./../../../../components/model-catalog/blueprint-model/test-blueprint/baseconfiguration") - - val executionContext = bluePrintRuntimeService.getExecutionContext() - - - componentNetconfExecutor.bluePrintRuntimeService = bluePrintRuntimeService - - //TODO("Set Attribute properties") - val stepMetaData: MutableMap = hashMapOf() - stepMetaData.putJsonElement(BluePrintConstants.PROPERTY_CURRENT_NODE_TEMPLATE, "activate-netconf") - stepMetaData.putJsonElement(BluePrintConstants.PROPERTY_CURRENT_INTERFACE, "ComponentNetconfExecutor") - stepMetaData.putJsonElement(BluePrintConstants.PROPERTY_CURRENT_OPERATION, "process") - // Set Step Inputs in Blueprint Runtime Service - bluePrintRuntimeService.put("activate-netconf-step-inputs", stepMetaData.asJsonNode()) - - componentNetconfExecutor.bluePrintRuntimeService = bluePrintRuntimeService - componentNetconfExecutor.stepName = "activate-netconf" - componentNetconfExecutor.apply(executionServiceInput) - - } -} - diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/NetconfSessionImplTest.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/NetconfSessionImplTest.kt deleted file mode 100644 index e7a514347..000000000 --- a/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/NetconfSessionImplTest.kt +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright © 2017-2018 AT&T Intellectual Property. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor - -import org.apache.sshd.client.channel.ChannelSubsystem -import org.apache.sshd.client.session.ClientSessionImpl -import org.junit.After -import org.junit.Assert -import org.junit.Before -import org.junit.Test -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.api.DeviceInfo -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.core.NetconfRpcServiceImpl -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.core.NetconfSessionImpl -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.mocks.NetconfDeviceSimulator -import java.util.concurrent.atomic.AtomicReference -import kotlin.script.experimental.api.asSuccess - -class NetconfSessionImplTest { - - private var device: NetconfDeviceSimulator? = null - private var deviceInfo: DeviceInfo? = null - - @Before - fun before() { - deviceInfo = DeviceInfo().apply { - username = "username" - password = "password" - ipAddress = "localhost" - port = 2224 - connectTimeout = 10 - } - - device = NetconfDeviceSimulator(deviceInfo!!.port) - device!!.start() - } - - @After - fun after() { - device!!.stop() - } - - @Throws(Exception::class) - fun testNetconfSession() { - val netconfSession = NetconfSessionImpl(deviceInfo!!, NetconfRpcServiceImpl(DeviceInfo())) - - Assert.assertNotNull(netconfSession.getSessionId()) - Assert.assertEquals("localhost:2224", netconfSession.getDeviceInfo().toString()) - - netconfSession.checkAndReestablish() - - Assert.assertNotNull(netconfSession.getSessionId()) - Assert.assertEquals("localhost:2224", netconfSession.getDeviceInfo().toString()) - - Assert.assertTrue(!netconfSession.getDeviceCapabilitiesSet().isEmpty()) - } - - @Test - fun testNetconfSessionconnect() { - val netconfSession = NetconfSessionImpl(deviceInfo!!, NetconfRpcServiceImpl(deviceInfo!!)) - netconfSession.connect() - Assert.assertTrue(netconfSession.sessionstatus("Open")) - } - - @Test - fun testNetconfSessionreconnect() { - val netconfSession = NetconfSessionImpl(deviceInfo!!, NetconfRpcServiceImpl(deviceInfo!!)) - netconfSession.connect() - netconfSession.reconnect() - Assert.assertTrue(netconfSession.sessionstatus("Open")) - - } - @Test - fun testNetconfSessiondisconnect() { - val netconfSession = NetconfSessionImpl(deviceInfo!!, NetconfRpcServiceImpl(deviceInfo!!)) - netconfSession.connect() - netconfSession.disconnect() - Assert.assertTrue(netconfSession.sessionstatus("Close")) - - } - @Test - fun testNetconfSessioncheckAndReestablish() { - val netconfSession = NetconfSessionImpl(deviceInfo!!, NetconfRpcServiceImpl(deviceInfo!!)) - netconfSession.connect() - netconfSession.checkAndReestablish() - Assert.assertTrue(netconfSession.sessionstatus("Open")) - - - } - @Test - fun testNetconfSessionconnecgetDeviceInfo() { - val netconfSession = NetconfSessionImpl(deviceInfo!!, NetconfRpcServiceImpl(deviceInfo!!)) - netconfSession.connect() - Assert.assertNotNull(netconfSession.getDeviceInfo()) - Assert.assertFalse(!netconfSession.getDeviceCapabilitiesSet().isEmpty()) - } - - -} diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/core/NetconfRpcServiceImplTest.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/core/NetconfRpcServiceImplTest.kt deleted file mode 100644 index 8f1f71501..000000000 --- a/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/core/NetconfRpcServiceImplTest.kt +++ /dev/null @@ -1,124 +0,0 @@ -package org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.core - -import org.junit.After -import org.junit.Assert -import org.junit.Before -import org.junit.Test - -import org.junit.Assert.* -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.api.DeviceInfo -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.mocks.NetconfDeviceSimulator - -class NetconfRpcServiceImplTest { - - private var device: NetconfDeviceSimulator? = null - private var deviceInfo: DeviceInfo? = null - - @Before - fun before() { - deviceInfo = DeviceInfo().apply { - username = "username" - password = "password" - ipAddress = "localhost" - port = 2224 - connectTimeout = 10 - } - - device = NetconfDeviceSimulator(deviceInfo!!.port) - device!!.start() - } - - @After - fun after() { - device!!.stop() - } - - @Test - fun setNetconfSession() { - - } - - @Test - fun getConfig() { - - val netconfRpcServiceImpl = NetconfRpcServiceImpl(deviceInfo!!) - val netconfSession = NetconfSessionImpl(deviceInfo!!, netconfRpcServiceImpl) - netconfRpcServiceImpl.setNetconfSession(netconfSession) - netconfSession.connect() - Assert.assertTrue(netconfRpcServiceImpl.getConfig("filter","target").status.equals("failure")) - } - - - @Test - fun deleteConfig() { - - val netconfRpcServiceImpl = NetconfRpcServiceImpl(deviceInfo!!) - val netconfSession = NetconfSessionImpl(deviceInfo!!, netconfRpcServiceImpl) - netconfRpcServiceImpl.setNetconfSession(netconfSession) - netconfSession.connect() - Assert.assertTrue(netconfRpcServiceImpl.deleteConfig("target").status.equals("failure")) - } - - @Test - fun lock() { - val netconfRpcServiceImpl = NetconfRpcServiceImpl(deviceInfo!!) - val netconfSession = NetconfSessionImpl(deviceInfo!!, netconfRpcServiceImpl) - netconfRpcServiceImpl.setNetconfSession(netconfSession) - netconfSession.connect() - Assert.assertTrue(netconfRpcServiceImpl.lock("target").status.equals("failure")) - } - - @Test - fun unLock() { - val netconfRpcServiceImpl = NetconfRpcServiceImpl(deviceInfo!!) - val netconfSession = NetconfSessionImpl(deviceInfo!!, netconfRpcServiceImpl) - netconfRpcServiceImpl.setNetconfSession(netconfSession) - netconfSession.connect() - Assert.assertTrue(netconfRpcServiceImpl.unLock("target").status.equals("failure")) - } - - @Test - fun commit() { - val netconfRpcServiceImpl = NetconfRpcServiceImpl(deviceInfo!!) - val netconfSession = NetconfSessionImpl(deviceInfo!!, netconfRpcServiceImpl) - netconfRpcServiceImpl.setNetconfSession(netconfSession) - netconfSession.connect() - Assert.assertTrue(netconfRpcServiceImpl.commit(true,60,"persist","1").status.equals("failure")) - - } - - @Test - fun cancelCommit() { - val netconfSession = NetconfSessionImpl(deviceInfo!!, NetconfRpcServiceImpl(DeviceInfo())) - val netconfRpcServiceImpl = NetconfRpcServiceImpl(DeviceInfo()) - netconfRpcServiceImpl.setNetconfSession(netconfSession) - netconfSession.connect() - - Assert.assertNotNull(netconfRpcServiceImpl.cancelCommit("1")) - } - - @Test - fun discardConfig() { - val netconfRpcServiceImpl = NetconfRpcServiceImpl(deviceInfo!!) - val netconfSession = NetconfSessionImpl(deviceInfo!!, netconfRpcServiceImpl) - netconfRpcServiceImpl.setNetconfSession(netconfSession) - netconfSession.connect() - Assert.assertTrue(netconfRpcServiceImpl.discardConfig().status.equals("failure")) - - } - - @Test - fun editConfig() { - } - - @Test - fun validate() { - val netconfRpcServiceImpl = NetconfRpcServiceImpl(deviceInfo!!) - val netconfSession = NetconfSessionImpl(deviceInfo!!, netconfRpcServiceImpl) - netconfRpcServiceImpl.setNetconfSession(netconfSession) - netconfSession.connect() - Assert.assertTrue(netconfRpcServiceImpl.validate("target").status.equals("failure")) - - } - -} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/mocks/NetconfDeviceSimulator.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/mocks/NetconfDeviceSimulator.kt deleted file mode 100644 index a2a3946db..000000000 --- a/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/mocks/NetconfDeviceSimulator.kt +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright © 2017-2018 AT&T Intellectual Property. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.mocks - - -import org.apache.sshd.common.NamedFactory -import org.apache.sshd.server.Command -import org.apache.sshd.server.SshServer -import org.apache.sshd.server.auth.UserAuth -import org.apache.sshd.server.auth.UserAuthNoneFactory -import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.utils.NetconfSubsystemFactory -import java.util.* - - -class NetconfDeviceSimulator(private val port: Int) { - - private var sshd: SshServer? = null - - fun start() { - sshd = SshServer.setUpDefaultServer() - sshd!!.port = port - sshd!!.keyPairProvider = SimpleGeneratorHostKeyProvider() - - val userAuthFactories = ArrayList>() - userAuthFactories.add(UserAuthNoneFactory()) - sshd!!.userAuthFactories = userAuthFactories - - val namedFactoryList = ArrayList>() - namedFactoryList.add(NetconfSubsystemFactory()) - sshd!!.subsystemFactories = namedFactoryList - - try { - sshd!!.start() - } catch (e: Exception) { - e.printStackTrace() - } - - } - - fun stop() { - try { - sshd!!.stop(true) - } catch (e: Exception) { - e.printStackTrace() - } - - } -} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/mocks/NetconfSubsystemFactory.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/mocks/NetconfSubsystemFactory.kt deleted file mode 100644 index 7eaef030b..000000000 --- a/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/mocks/NetconfSubsystemFactory.kt +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright © 2017-2018 AT&T Intellectual Property. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.utils - - -import java.io.IOException -import java.io.InputStream -import java.io.OutputStream -import org.apache.sshd.common.NamedFactory; -import org.apache.sshd.server.Command; -import org.apache.sshd.server.Environment; -import org.apache.sshd.server.ExitCallback; - - -class NetconfSubsystemFactory : NamedFactory { - - private val END_CHAR_SEQUENCE = "]]>]]>" - - override fun create(): Command { - return NetconfSubsystem() - } - - override fun getName(): String { - return "netconf" - } - - /** - * Simple implementation of netconf reading 1 request, sending a 'hello' response and quitting - */ - inner class NetconfSubsystem : Command { - private var input: InputStream? = null - private var out: OutputStream? = null - private var clientThread: Thread? = null - private var r: Int = 0 - - @Throws(IOException::class) - override fun start(env: Environment) { - clientThread = Thread(object : Runnable { - - override fun run() { - try { - val message = StringBuilder() - while (true) { - process(createHelloString()) - r = input!!.read() - if (r == -1) { - break - } else { - val c = r.toChar() - message.append(c) - val messageString = message.toString() - if (messageString.endsWith(END_CHAR_SEQUENCE)) { - println("Detected end message:\n$messageString") - process(createHelloString()) - message.setLength(0) - break - } - } - } - } catch (e: IOException) { - e.printStackTrace() - } - - } - - @Throws(IOException::class) - private fun process(xmlMessage: String) { - println("Sending message:\n$xmlMessage") - out!!.write(xmlMessage.toByteArray(charset("UTF-8"))) - out!!.write((END_CHAR_SEQUENCE + "\n").toByteArray(charset("UTF-8"))) - out!!.flush() - } - - private fun createHelloString(): String { - val sessionId = "" + (Math.random() * Integer.MAX_VALUE).toInt() - return ("\n" - + "\nurn:ietf:params:netconf:base:1.0\n" - + "urn:ietf:params:netconf:base:1.1\n\n" - + "" + sessionId + "\n") - } - }) - - clientThread!!.start() - } - - @Throws(Exception::class) - override fun destroy() { - try { - clientThread!!.join(2000) - } catch (e: InterruptedException) { - // log.warn("Error joining Client thread" + e.getMessage()); - } - - clientThread!!.interrupt() - } - - override fun setInputStream(input: InputStream) { - this.input = input - } - - override fun setOutputStream(out: OutputStream) { - this.out = out - } - - override fun setErrorStream(err: OutputStream) {} - - override fun setExitCallback(callback: ExitCallback) {} - - - - } -} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/utils/RpcMessageUtilsTest.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/utils/RpcMessageUtilsTest.kt deleted file mode 100644 index 8a60d8097..000000000 --- a/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/netconf/executor/utils/RpcMessageUtilsTest.kt +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright © 2017-2018 AT&T Intellectual Property. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.utils - -import org.junit.Assert -import org.junit.Assert.assertTrue -import org.junit.Test -import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.api.NetconfException -import kotlin.test.fail - -class RpcMessageUtilsTest { - - @Test - fun getConfig() { - val checkString = ("" - + "" - + "Test-Filter-Content" - + "") - - val messageId = "Test-Message-ID" - val configType = NetconfDatastore.CANDIDATE.datastore - val filterContent = "Test-Filter-Content" - - val result = - NetconfMessageUtils.getConfig(messageId, configType, filterContent).replace("[\n\r\t]".toRegex(), "") - - assertTrue(NetconfMessageUtils.validateRPCXML(result)) - Assert.assertEquals(checkString, result) - } - - - @Test - fun editConfig() { - val checkString = ("" - + "" - + "Test-Default-Operation" - + "Test-Filter-Content") - - val messageId = "Test-Message-ID" - val configType = NetconfDatastore.CANDIDATE.datastore - val filterContent = "Test-Filter-Content" - val defaultOperation = "Test-Default-Operation" - - val result = - NetconfMessageUtils.editConfig(messageId, configType, defaultOperation, filterContent).replace("[\n\r\t]".toRegex(), "") - - assertTrue(NetconfMessageUtils.validateRPCXML(result)) - Assert.assertEquals(checkString, result) - } - - @Test - fun validate() { - val checkString = ("" - + "" - + "") - - val messageId = "Test-Message-ID" - val configType = NetconfDatastore.CANDIDATE.datastore - - val result = NetconfMessageUtils.validate(messageId, configType).replace("[\n\r\t]".toRegex(), "") - - assertTrue(NetconfMessageUtils.validateRPCXML(result)) - Assert.assertEquals(checkString, result) - } - - @Test - fun cancelCommit() { - val checkString = - ("" + - "" + - "" + - "1234" + - "") - - val messageId = "Test-Message-ID" - - val cancelCommitPersistId = - NetconfMessageUtils.cancelCommit(messageId, "1234").replace("[\n\r\t]".toRegex(), "") - - assertTrue(NetconfMessageUtils.validateRPCXML(cancelCommitPersistId)) - Assert.assertEquals(checkString, cancelCommitPersistId) - } - - @Test - fun cancelCommitNoPersistId() { - val checkString = - ("" + - "" + - "" + - "") - - val messageId = "Test-Message-ID" - - val cancelCommitNoPersistId = NetconfMessageUtils.cancelCommit(messageId, "").replace("[\n\r\t]".toRegex(), "") - - assertTrue(NetconfMessageUtils.validateRPCXML(cancelCommitNoPersistId)) - Assert.assertEquals(checkString, cancelCommitNoPersistId) - } - - @Test - fun commit() { - val checkString = ("" - + "" - + "") - - val messageId = "Test-Message-ID" - - val commit = NetconfMessageUtils.commit(messageId, false, 0, "", "").replace("[\n\r\t]".toRegex(), "") - - val commitWithPersistButNotConfirmed = - NetconfMessageUtils.commit(messageId, false, 0, "1234", "").replace("[\n\r\t]".toRegex(), "") - - assertTrue(NetconfMessageUtils.validateRPCXML(commit)) - Assert.assertEquals(checkString, commit) - Assert.assertEquals(checkString, commitWithPersistButNotConfirmed) - - } - - @Test - fun commitPersistId() { - val checkString = - ("" + - "" + - "" + - "1234" + - "") - - val messageId = "Test-Message-ID" - - val result = NetconfMessageUtils.commit(messageId, false, 30, "", "1234").replace("[\n\r\t]".toRegex(), "") - assertTrue(NetconfMessageUtils.validateRPCXML(result)) - Assert.assertEquals(checkString, result) - - try { - NetconfMessageUtils.commit(messageId, true, 30, "", "1234").replace("[\n\r\t]".toRegex(), "") - } catch (e: NetconfException) { - Assert.assertEquals("Can't proceed with both confirmed flag and persistId(1234) specified. Only one should be specified.", - e.message) - return - } - - fail() - } - - @Test - fun commitPersist() { - val checkString = - ("" + - "" + - "" + - "" + - "30" + - "1234" + - "") - - val messageId = "Test-Message-ID" - - val result = NetconfMessageUtils.commit(messageId, true, 30, "1234", "").replace("[\n\r\t]".toRegex(), "") - - assertTrue(NetconfMessageUtils.validateRPCXML(result)) - Assert.assertEquals(checkString, result) - - try { - NetconfMessageUtils.commit(messageId, false, 30, "1234", "1234").replace("[\n\r\t]".toRegex(), "") - } catch (e: NetconfException) { - Assert.assertEquals("Can't proceed with both persist(1234) and persistId(1234) specified. Only one should be specified.", - e.message) - return - } - fail() - } - - @Test - fun unlock() { - val checkString = ("" - + "" - + "") - - val messageId = "Test-Message-ID" - val configType = NetconfDatastore.CANDIDATE.datastore - - val result = NetconfMessageUtils.unlock(messageId, configType).replace("[\n\r\t]".toRegex(), "") - - assertTrue(NetconfMessageUtils.validateRPCXML(result)) - Assert.assertEquals(checkString, result) - } - - @Test - fun deleteConfig() { - val checkString = ("" - + "" - + "") - - val messageId = "Test-Message-ID" - val netconfTargetConfig = NetconfDatastore.CANDIDATE.datastore - - val result = NetconfMessageUtils.deleteConfig(messageId, netconfTargetConfig).replace("[\n\r\t]".toRegex(), "") - - assertTrue(NetconfMessageUtils.validateRPCXML(result)) - Assert.assertEquals(checkString, result) - } - - @Test - fun discardChanges() { - val checkString = ("" - + "" - + "") - - val messageId = "Test-Message-ID" - - val result = NetconfMessageUtils.discardChanges(messageId).replace("[\n\r\t]".toRegex(), "") - - assertTrue(NetconfMessageUtils.validateRPCXML(result)) - Assert.assertEquals(checkString, result) - } - - @Test - fun lock() { - val checkString = ("" - + "" - + "") - - val messageId = "Test-Message-ID" - val configType = NetconfDatastore.CANDIDATE.datastore - val result = NetconfMessageUtils.lock(messageId, configType).replace("[\n\r\t]".toRegex(), "") - - assertTrue(NetconfMessageUtils.validateRPCXML(result)) - Assert.assertEquals(checkString, result) - } - - @Test - fun getMsgId() { - val checkString = ("testmessage") - - var messageId = "message-id=\"testmessage\"" - var result = NetconfMessageUtils.getMsgId(messageId).replace("[\n\r\t]".toRegex(), "") - Assert.assertEquals(checkString, result) - - messageId = "message-id=\"hello\"" - result = NetconfMessageUtils.getMsgId(messageId).replace("[\n\r\t]".toRegex(), "") - Assert.assertEquals("hello", result) - - messageId = "message-id" - result = NetconfMessageUtils.getMsgId(messageId).replace("[\n\r\t]".toRegex(), "") - Assert.assertEquals("", result) - } - - @Test - fun createHelloString() { - val checkString = (" " - +" hi hello ]]>]]>") - - val capability = listOf("hi", "hello") - - val result = NetconfMessageUtils.createHelloString(capability).replace("[\n\r\t]".toRegex(), "") - Assert.assertEquals(checkString, result) - } - - @Test - fun validateChunkedFraming() { - val reply = ("hello") - val result = NetconfMessageUtils.validateChunkedFraming(reply) - Assert.assertFalse(result) - } - - @Test - fun checkReply(){ - assertTrue(NetconfMessageUtils.checkReply("ok")) - } - - @Test - fun formatRPCRequest(){ - val checkString = ("#199" + - " hi hello " + - "##") - - val request = (" " - +" hi hello ]]>]]>") - - val messageId = "Test-Message-ID" - - val capabilities = setOf("hi", "hello","urn:ietf:params:netconf:base:1.1") - - val result = NetconfMessageUtils.formatRPCRequest(request,messageId,capabilities).replace("[\n\r\t]".toRegex(), "") - Assert.assertEquals(checkString, result) - - - } - - - - -} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/ComponentNetconfExecutorTest.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/ComponentNetconfExecutorTest.kt new file mode 100644 index 000000000..b84c2d1ae --- /dev/null +++ b/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/ComponentNetconfExecutorTest.kt @@ -0,0 +1,79 @@ +/* + * Copyright © 2017-2018 AT&T Intellectual Property. + * + * Modifications Copyright © 2019 IBM, Bell Canada. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor + +import com.fasterxml.jackson.databind.JsonNode +import org.junit.Test +import org.junit.runner.RunWith +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants +import org.onap.ccsdk.cds.controllerblueprints.core.asJsonNode +import org.onap.ccsdk.cds.controllerblueprints.core.putJsonElement +import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils +import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.autoconfigure.EnableAutoConfiguration +import org.springframework.context.annotation.ComponentScan +import org.springframework.test.annotation.DirtiesContext +import org.springframework.test.context.TestPropertySource +import org.springframework.test.context.junit4.SpringRunner + +@RunWith(SpringRunner::class) +@EnableAutoConfiguration +@ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"]) +@DirtiesContext +@TestPropertySource(properties = +["blueprints.processor.functions.python.executor.modulePaths=./../../../../components/scripts/python/ccsdk_netconf,./../../../../components/scripts/python/ccsdk_blueprints", + "blueprints.processor.functions.python.executor.executionPath=./../../../../components/scripts/python/ccsdk_netconf"], + locations = ["classpath:application-test.properties"]) +class ComponentNetconfExecutorTest { + + @Autowired + lateinit var componentNetconfExecutor: ComponentNetconfExecutor + + + @Test + fun testComponentNetconfExecutor() { + + val executionServiceInput = JacksonUtils.readValueFromClassPathFile("requests/sample-activate-request.json", + ExecutionServiceInput::class.java)!! + + val bluePrintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime("1234", + "./../../../../components/model-catalog/blueprint-model/test-blueprint/baseconfiguration") + + val executionContext = bluePrintRuntimeService.getExecutionContext() + + + componentNetconfExecutor.bluePrintRuntimeService = bluePrintRuntimeService + + //TODO("Set Attribute properties") + val stepMetaData: MutableMap = hashMapOf() + stepMetaData.putJsonElement(BluePrintConstants.PROPERTY_CURRENT_NODE_TEMPLATE, "activate-netconf") + stepMetaData.putJsonElement(BluePrintConstants.PROPERTY_CURRENT_INTERFACE, "ComponentNetconfExecutor") + stepMetaData.putJsonElement(BluePrintConstants.PROPERTY_CURRENT_OPERATION, "process") + // Set Step Inputs in Blueprint Runtime Service + bluePrintRuntimeService.put("activate-netconf-step-inputs", stepMetaData.asJsonNode()) + + componentNetconfExecutor.bluePrintRuntimeService = bluePrintRuntimeService + componentNetconfExecutor.stepName = "activate-netconf" + componentNetconfExecutor.apply(executionServiceInput) + + } +} + diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/NetconfSessionImplTest.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/NetconfSessionImplTest.kt new file mode 100644 index 000000000..b462ad0e8 --- /dev/null +++ b/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/NetconfSessionImplTest.kt @@ -0,0 +1,111 @@ +/* + * Copyright © 2017-2018 AT&T Intellectual Property. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor + +import org.apache.sshd.client.channel.ChannelSubsystem +import org.apache.sshd.client.session.ClientSessionImpl +import org.junit.After +import org.junit.Assert +import org.junit.Before +import org.junit.Test +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.DeviceInfo +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.core.NetconfRpcServiceImpl +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.core.NetconfSessionImpl +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.mocks.NetconfDeviceSimulator +import java.util.concurrent.atomic.AtomicReference +import kotlin.script.experimental.api.asSuccess + +class NetconfSessionImplTest { + + private var device: NetconfDeviceSimulator? = null + private var deviceInfo: DeviceInfo? = null + + @Before + fun before() { + deviceInfo = DeviceInfo().apply { + username = "username" + password = "password" + ipAddress = "localhost" + port = 2224 + connectTimeout = 10 + } + + device = NetconfDeviceSimulator(deviceInfo!!.port) + device!!.start() + } + + @After + fun after() { + device!!.stop() + } + + @Throws(Exception::class) + fun testNetconfSession() { + val netconfSession = NetconfSessionImpl(deviceInfo!!, NetconfRpcServiceImpl(DeviceInfo())) + + Assert.assertNotNull(netconfSession.getSessionId()) + Assert.assertEquals("localhost:2224", netconfSession.getDeviceInfo().toString()) + + netconfSession.checkAndReestablish() + + Assert.assertNotNull(netconfSession.getSessionId()) + Assert.assertEquals("localhost:2224", netconfSession.getDeviceInfo().toString()) + + Assert.assertTrue(!netconfSession.getDeviceCapabilitiesSet().isEmpty()) + } + + @Test + fun testNetconfSessionconnect() { + val netconfSession = NetconfSessionImpl(deviceInfo!!, NetconfRpcServiceImpl(deviceInfo!!)) + netconfSession.connect() + Assert.assertTrue(netconfSession.sessionstatus("Open")) + } + + @Test + fun testNetconfSessionreconnect() { + val netconfSession = NetconfSessionImpl(deviceInfo!!, NetconfRpcServiceImpl(deviceInfo!!)) + netconfSession.connect() + netconfSession.reconnect() + Assert.assertTrue(netconfSession.sessionstatus("Open")) + + } + @Test + fun testNetconfSessiondisconnect() { + val netconfSession = NetconfSessionImpl(deviceInfo!!, NetconfRpcServiceImpl(deviceInfo!!)) + netconfSession.connect() + netconfSession.disconnect() + Assert.assertTrue(netconfSession.sessionstatus("Close")) + + } + @Test + fun testNetconfSessioncheckAndReestablish() { + val netconfSession = NetconfSessionImpl(deviceInfo!!, NetconfRpcServiceImpl(deviceInfo!!)) + netconfSession.connect() + netconfSession.checkAndReestablish() + Assert.assertTrue(netconfSession.sessionstatus("Open")) + + + } + @Test + fun testNetconfSessionconnecgetDeviceInfo() { + val netconfSession = NetconfSessionImpl(deviceInfo!!, NetconfRpcServiceImpl(deviceInfo!!)) + netconfSession.connect() + Assert.assertNotNull(netconfSession.getDeviceInfo()) + Assert.assertFalse(!netconfSession.getDeviceCapabilitiesSet().isEmpty()) + } + + +} diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfRpcServiceImplTest.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfRpcServiceImplTest.kt new file mode 100644 index 000000000..68d3e246f --- /dev/null +++ b/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfRpcServiceImplTest.kt @@ -0,0 +1,124 @@ +package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.core + +import org.junit.After +import org.junit.Assert +import org.junit.Before +import org.junit.Test + +import org.junit.Assert.* +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.DeviceInfo +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.mocks.NetconfDeviceSimulator + +class NetconfRpcServiceImplTest { + + private var device: NetconfDeviceSimulator? = null + private var deviceInfo: DeviceInfo? = null + + @Before + fun before() { + deviceInfo = DeviceInfo().apply { + username = "username" + password = "password" + ipAddress = "localhost" + port = 2224 + connectTimeout = 10 + } + + device = NetconfDeviceSimulator(deviceInfo!!.port) + device!!.start() + } + + @After + fun after() { + device!!.stop() + } + + @Test + fun setNetconfSession() { + + } + + @Test + fun getConfig() { + + val netconfRpcServiceImpl = NetconfRpcServiceImpl(deviceInfo!!) + val netconfSession = NetconfSessionImpl(deviceInfo!!, netconfRpcServiceImpl) + netconfRpcServiceImpl.setNetconfSession(netconfSession) + netconfSession.connect() + Assert.assertTrue(netconfRpcServiceImpl.getConfig("filter","target").status.equals("failure")) + } + + + @Test + fun deleteConfig() { + + val netconfRpcServiceImpl = NetconfRpcServiceImpl(deviceInfo!!) + val netconfSession = NetconfSessionImpl(deviceInfo!!, netconfRpcServiceImpl) + netconfRpcServiceImpl.setNetconfSession(netconfSession) + netconfSession.connect() + Assert.assertTrue(netconfRpcServiceImpl.deleteConfig("target").status.equals("failure")) + } + + @Test + fun lock() { + val netconfRpcServiceImpl = NetconfRpcServiceImpl(deviceInfo!!) + val netconfSession = NetconfSessionImpl(deviceInfo!!, netconfRpcServiceImpl) + netconfRpcServiceImpl.setNetconfSession(netconfSession) + netconfSession.connect() + Assert.assertTrue(netconfRpcServiceImpl.lock("target").status.equals("failure")) + } + + @Test + fun unLock() { + val netconfRpcServiceImpl = NetconfRpcServiceImpl(deviceInfo!!) + val netconfSession = NetconfSessionImpl(deviceInfo!!, netconfRpcServiceImpl) + netconfRpcServiceImpl.setNetconfSession(netconfSession) + netconfSession.connect() + Assert.assertTrue(netconfRpcServiceImpl.unLock("target").status.equals("failure")) + } + + @Test + fun commit() { + val netconfRpcServiceImpl = NetconfRpcServiceImpl(deviceInfo!!) + val netconfSession = NetconfSessionImpl(deviceInfo!!, netconfRpcServiceImpl) + netconfRpcServiceImpl.setNetconfSession(netconfSession) + netconfSession.connect() + Assert.assertTrue(netconfRpcServiceImpl.commit(true,60,"persist","1").status.equals("failure")) + + } + + @Test + fun cancelCommit() { + val netconfSession = NetconfSessionImpl(deviceInfo!!, NetconfRpcServiceImpl(DeviceInfo())) + val netconfRpcServiceImpl = NetconfRpcServiceImpl(DeviceInfo()) + netconfRpcServiceImpl.setNetconfSession(netconfSession) + netconfSession.connect() + + Assert.assertNotNull(netconfRpcServiceImpl.cancelCommit("1")) + } + + @Test + fun discardConfig() { + val netconfRpcServiceImpl = NetconfRpcServiceImpl(deviceInfo!!) + val netconfSession = NetconfSessionImpl(deviceInfo!!, netconfRpcServiceImpl) + netconfRpcServiceImpl.setNetconfSession(netconfSession) + netconfSession.connect() + Assert.assertTrue(netconfRpcServiceImpl.discardConfig().status.equals("failure")) + + } + + @Test + fun editConfig() { + } + + @Test + fun validate() { + val netconfRpcServiceImpl = NetconfRpcServiceImpl(deviceInfo!!) + val netconfSession = NetconfSessionImpl(deviceInfo!!, netconfRpcServiceImpl) + netconfRpcServiceImpl.setNetconfSession(netconfSession) + netconfSession.connect() + Assert.assertTrue(netconfRpcServiceImpl.validate("target").status.equals("failure")) + + } + +} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/mocks/NetconfDeviceSimulator.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/mocks/NetconfDeviceSimulator.kt new file mode 100644 index 000000000..c6d6308ab --- /dev/null +++ b/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/mocks/NetconfDeviceSimulator.kt @@ -0,0 +1,62 @@ +/* + * Copyright © 2017-2018 AT&T Intellectual Property. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.mocks + + +import org.apache.sshd.common.NamedFactory +import org.apache.sshd.server.Command +import org.apache.sshd.server.SshServer +import org.apache.sshd.server.auth.UserAuth +import org.apache.sshd.server.auth.UserAuthNoneFactory +import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.utils.NetconfSubsystemFactory +import java.util.* + + +class NetconfDeviceSimulator(private val port: Int) { + + private var sshd: SshServer? = null + + fun start() { + sshd = SshServer.setUpDefaultServer() + sshd!!.port = port + sshd!!.keyPairProvider = SimpleGeneratorHostKeyProvider() + + val userAuthFactories = ArrayList>() + userAuthFactories.add(UserAuthNoneFactory()) + sshd!!.userAuthFactories = userAuthFactories + + val namedFactoryList = ArrayList>() + namedFactoryList.add(NetconfSubsystemFactory()) + sshd!!.subsystemFactories = namedFactoryList + + try { + sshd!!.start() + } catch (e: Exception) { + e.printStackTrace() + } + + } + + fun stop() { + try { + sshd!!.stop(true) + } catch (e: Exception) { + e.printStackTrace() + } + + } +} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/mocks/NetconfSubsystemFactory.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/mocks/NetconfSubsystemFactory.kt new file mode 100644 index 000000000..de0a5d016 --- /dev/null +++ b/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/mocks/NetconfSubsystemFactory.kt @@ -0,0 +1,125 @@ +/* + * Copyright © 2017-2018 AT&T Intellectual Property. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.utils + + +import java.io.IOException +import java.io.InputStream +import java.io.OutputStream +import org.apache.sshd.common.NamedFactory; +import org.apache.sshd.server.Command; +import org.apache.sshd.server.Environment; +import org.apache.sshd.server.ExitCallback; + + +class NetconfSubsystemFactory : NamedFactory { + + private val END_CHAR_SEQUENCE = "]]>]]>" + + override fun create(): Command { + return NetconfSubsystem() + } + + override fun getName(): String { + return "netconf" + } + + /** + * Simple implementation of netconf reading 1 request, sending a 'hello' response and quitting + */ + inner class NetconfSubsystem : Command { + private var input: InputStream? = null + private var out: OutputStream? = null + private var clientThread: Thread? = null + private var r: Int = 0 + + @Throws(IOException::class) + override fun start(env: Environment) { + clientThread = Thread(object : Runnable { + + override fun run() { + try { + val message = StringBuilder() + while (true) { + process(createHelloString()) + r = input!!.read() + if (r == -1) { + break + } else { + val c = r.toChar() + message.append(c) + val messageString = message.toString() + if (messageString.endsWith(END_CHAR_SEQUENCE)) { + println("Detected end message:\n$messageString") + process(createHelloString()) + message.setLength(0) + break + } + } + } + } catch (e: IOException) { + e.printStackTrace() + } + + } + + @Throws(IOException::class) + private fun process(xmlMessage: String) { + println("Sending message:\n$xmlMessage") + out!!.write(xmlMessage.toByteArray(charset("UTF-8"))) + out!!.write((END_CHAR_SEQUENCE + "\n").toByteArray(charset("UTF-8"))) + out!!.flush() + } + + private fun createHelloString(): String { + val sessionId = "" + (Math.random() * Integer.MAX_VALUE).toInt() + return ("\n" + + "\nurn:ietf:params:netconf:base:1.0\n" + + "urn:ietf:params:netconf:base:1.1\n\n" + + "" + sessionId + "\n") + } + }) + + clientThread!!.start() + } + + @Throws(Exception::class) + override fun destroy() { + try { + clientThread!!.join(2000) + } catch (e: InterruptedException) { + // log.warn("Error joining Client thread" + e.getMessage()); + } + + clientThread!!.interrupt() + } + + override fun setInputStream(input: InputStream) { + this.input = input + } + + override fun setOutputStream(out: OutputStream) { + this.out = out + } + + override fun setErrorStream(err: OutputStream) {} + + override fun setExitCallback(callback: ExitCallback) {} + + + + } +} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/utils/RpcMessageUtilsTest.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/utils/RpcMessageUtilsTest.kt new file mode 100644 index 000000000..a4ef4410a --- /dev/null +++ b/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/utils/RpcMessageUtilsTest.kt @@ -0,0 +1,306 @@ +/* + * Copyright © 2017-2018 AT&T Intellectual Property. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.utils + +import org.junit.Assert +import org.junit.Assert.assertTrue +import org.junit.Test +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.NetconfException +import kotlin.test.fail + +class RpcMessageUtilsTest { + + @Test + fun getConfig() { + val checkString = ("" + + "" + + "Test-Filter-Content" + + "") + + val messageId = "Test-Message-ID" + val configType = NetconfDatastore.CANDIDATE.datastore + val filterContent = "Test-Filter-Content" + + val result = + NetconfMessageUtils.getConfig(messageId, configType, filterContent).replace("[\n\r\t]".toRegex(), "") + + assertTrue(NetconfMessageUtils.validateRPCXML(result)) + Assert.assertEquals(checkString, result) + } + + + @Test + fun editConfig() { + val checkString = ("" + + "" + + "Test-Default-Operation" + + "Test-Filter-Content") + + val messageId = "Test-Message-ID" + val configType = NetconfDatastore.CANDIDATE.datastore + val filterContent = "Test-Filter-Content" + val defaultOperation = "Test-Default-Operation" + + val result = + NetconfMessageUtils.editConfig(messageId, configType, defaultOperation, filterContent).replace("[\n\r\t]".toRegex(), "") + + assertTrue(NetconfMessageUtils.validateRPCXML(result)) + Assert.assertEquals(checkString, result) + } + + @Test + fun validate() { + val checkString = ("" + + "" + + "") + + val messageId = "Test-Message-ID" + val configType = NetconfDatastore.CANDIDATE.datastore + + val result = NetconfMessageUtils.validate(messageId, configType).replace("[\n\r\t]".toRegex(), "") + + assertTrue(NetconfMessageUtils.validateRPCXML(result)) + Assert.assertEquals(checkString, result) + } + + @Test + fun cancelCommit() { + val checkString = + ("" + + "" + + "" + + "1234" + + "") + + val messageId = "Test-Message-ID" + + val cancelCommitPersistId = + NetconfMessageUtils.cancelCommit(messageId, "1234").replace("[\n\r\t]".toRegex(), "") + + assertTrue(NetconfMessageUtils.validateRPCXML(cancelCommitPersistId)) + Assert.assertEquals(checkString, cancelCommitPersistId) + } + + @Test + fun cancelCommitNoPersistId() { + val checkString = + ("" + + "" + + "" + + "") + + val messageId = "Test-Message-ID" + + val cancelCommitNoPersistId = NetconfMessageUtils.cancelCommit(messageId, "").replace("[\n\r\t]".toRegex(), "") + + assertTrue(NetconfMessageUtils.validateRPCXML(cancelCommitNoPersistId)) + Assert.assertEquals(checkString, cancelCommitNoPersistId) + } + + @Test + fun commit() { + val checkString = ("" + + "" + + "") + + val messageId = "Test-Message-ID" + + val commit = NetconfMessageUtils.commit(messageId, false, 0, "", "").replace("[\n\r\t]".toRegex(), "") + + val commitWithPersistButNotConfirmed = + NetconfMessageUtils.commit(messageId, false, 0, "1234", "").replace("[\n\r\t]".toRegex(), "") + + assertTrue(NetconfMessageUtils.validateRPCXML(commit)) + Assert.assertEquals(checkString, commit) + Assert.assertEquals(checkString, commitWithPersistButNotConfirmed) + + } + + @Test + fun commitPersistId() { + val checkString = + ("" + + "" + + "" + + "1234" + + "") + + val messageId = "Test-Message-ID" + + val result = NetconfMessageUtils.commit(messageId, false, 30, "", "1234").replace("[\n\r\t]".toRegex(), "") + assertTrue(NetconfMessageUtils.validateRPCXML(result)) + Assert.assertEquals(checkString, result) + + try { + NetconfMessageUtils.commit(messageId, true, 30, "", "1234").replace("[\n\r\t]".toRegex(), "") + } catch (e: NetconfException) { + Assert.assertEquals("Can't proceed with both confirmed flag and persistId(1234) specified. Only one should be specified.", + e.message) + return + } + + fail() + } + + @Test + fun commitPersist() { + val checkString = + ("" + + "" + + "" + + "" + + "30" + + "1234" + + "") + + val messageId = "Test-Message-ID" + + val result = NetconfMessageUtils.commit(messageId, true, 30, "1234", "").replace("[\n\r\t]".toRegex(), "") + + assertTrue(NetconfMessageUtils.validateRPCXML(result)) + Assert.assertEquals(checkString, result) + + try { + NetconfMessageUtils.commit(messageId, false, 30, "1234", "1234").replace("[\n\r\t]".toRegex(), "") + } catch (e: NetconfException) { + Assert.assertEquals("Can't proceed with both persist(1234) and persistId(1234) specified. Only one should be specified.", + e.message) + return + } + fail() + } + + @Test + fun unlock() { + val checkString = ("" + + "" + + "") + + val messageId = "Test-Message-ID" + val configType = NetconfDatastore.CANDIDATE.datastore + + val result = NetconfMessageUtils.unlock(messageId, configType).replace("[\n\r\t]".toRegex(), "") + + assertTrue(NetconfMessageUtils.validateRPCXML(result)) + Assert.assertEquals(checkString, result) + } + + @Test + fun deleteConfig() { + val checkString = ("" + + "" + + "") + + val messageId = "Test-Message-ID" + val netconfTargetConfig = NetconfDatastore.CANDIDATE.datastore + + val result = NetconfMessageUtils.deleteConfig(messageId, netconfTargetConfig).replace("[\n\r\t]".toRegex(), "") + + assertTrue(NetconfMessageUtils.validateRPCXML(result)) + Assert.assertEquals(checkString, result) + } + + @Test + fun discardChanges() { + val checkString = ("" + + "" + + "") + + val messageId = "Test-Message-ID" + + val result = NetconfMessageUtils.discardChanges(messageId).replace("[\n\r\t]".toRegex(), "") + + assertTrue(NetconfMessageUtils.validateRPCXML(result)) + Assert.assertEquals(checkString, result) + } + + @Test + fun lock() { + val checkString = ("" + + "" + + "") + + val messageId = "Test-Message-ID" + val configType = NetconfDatastore.CANDIDATE.datastore + val result = NetconfMessageUtils.lock(messageId, configType).replace("[\n\r\t]".toRegex(), "") + + assertTrue(NetconfMessageUtils.validateRPCXML(result)) + Assert.assertEquals(checkString, result) + } + + @Test + fun getMsgId() { + val checkString = ("testmessage") + + var messageId = "message-id=\"testmessage\"" + var result = NetconfMessageUtils.getMsgId(messageId).replace("[\n\r\t]".toRegex(), "") + Assert.assertEquals(checkString, result) + + messageId = "message-id=\"hello\"" + result = NetconfMessageUtils.getMsgId(messageId).replace("[\n\r\t]".toRegex(), "") + Assert.assertEquals("hello", result) + + messageId = "message-id" + result = NetconfMessageUtils.getMsgId(messageId).replace("[\n\r\t]".toRegex(), "") + Assert.assertEquals("", result) + } + + @Test + fun createHelloString() { + val checkString = (" " + +" hi hello ]]>]]>") + + val capability = listOf("hi", "hello") + + val result = NetconfMessageUtils.createHelloString(capability).replace("[\n\r\t]".toRegex(), "") + Assert.assertEquals(checkString, result) + } + + @Test + fun validateChunkedFraming() { + val reply = ("hello") + val result = NetconfMessageUtils.validateChunkedFraming(reply) + Assert.assertFalse(result) + } + + @Test + fun checkReply(){ + assertTrue(NetconfMessageUtils.checkReply("ok")) + } + + @Test + fun formatRPCRequest(){ + val checkString = ("#199" + + " hi hello " + + "##") + + val request = (" " + +" hi hello ]]>]]>") + + val messageId = "Test-Message-ID" + + val capabilities = setOf("hi", "hello","urn:ietf:params:netconf:base:1.1") + + val result = NetconfMessageUtils.formatRPCRequest(request,messageId,capabilities).replace("[\n\r\t]".toRegex(), "") + Assert.assertEquals(checkString, result) + + + } + + + + +} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/logback-test.xml b/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/logback-test.xml index f9ec9fe57..355cd3ace 100644 --- a/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/logback-test.xml +++ b/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/logback-test.xml @@ -26,7 +26,7 @@ - + -- cgit 1.2.3-korg