2 * Copyright © 2017-2019 AT&T, Bell Canada
3 * Modifications Copyright (c) 2019 IBM, Bell Canada
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.core
20 import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.*
21 import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.utils.NetconfMessageUtils
22 import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.utils.RpcStatus
23 import org.slf4j.LoggerFactory
24 import java.util.concurrent.TimeUnit
25 import java.util.concurrent.atomic.AtomicInteger
27 class NetconfRpcServiceImpl(private var deviceInfo: DeviceInfo) : NetconfRpcService {
29 private val log = LoggerFactory.getLogger(NetconfRpcService::class.java)
31 private var responseTimeout: Int = deviceInfo.replyTimeout
33 private lateinit var netconfSession: NetconfSession
35 private val messageIdInteger = AtomicInteger(1)
37 fun setNetconfSession(netconfSession: NetconfSession) {
38 this.netconfSession = netconfSession
42 * accept a user-supplied RPC message WITH HEADER
43 * <rpc message-id="abc123" xmlns=".....">
48 * and replace the user-supplied message-id with the one that is passed.
49 * Used by NetconfRpcServiceImpl.invokeRpc to keep the message-id consistent
50 * with auto-incremented numbering scheme.
51 * @param rpc: Complete custom RPC call including the header
52 * @param updatedMessageID new message-id to substitute
53 * @return updated RPC message with message-id replaced.
55 private fun replaceUserSuppliedNetconfMessageID(rpc: String, updatedMessageID: String): String {
56 return rpc.replaceFirst("message-id=\".+\"".toRegex(), "message-id=\"$updatedMessageID\"")
59 override fun invokeRpc(rpc: String): DeviceResponse {
60 var output = DeviceResponse()
61 //Attempt to extract the message-id field from the <rpc call
62 val updatedMessageId = messageIdInteger.getAndIncrement().toString()
63 val origMessageId = NetconfMessageUtils.getMsgId(rpc)
64 log.info("$deviceInfo: invokeRpc: updating rpc original message-id:($origMessageId) to messageId($updatedMessageId)")
66 output = asyncRpc(replaceUserSuppliedNetconfMessageID(rpc, updatedMessageId), updatedMessageId)
67 } catch (e: Exception) {
68 output.status = RpcStatus.FAILURE
69 output.errorMessage = "$deviceInfo: failed in 'invokeRpc' command. Message: ${e.message}."
70 log.error("$deviceInfo: failed in 'invokeRpc' command. Exception: $e")
75 override fun get(filter: String): DeviceResponse {
76 var output = DeviceResponse()
77 val messageId = messageIdInteger.getAndIncrement().toString()
78 log.info("$deviceInfo: get operational config: messageId($messageId)")
80 val message = NetconfMessageUtils.get(messageId, filter)
81 output = asyncRpc(message, messageId)
82 } catch (e: Exception) {
83 output.status = RpcStatus.FAILURE
84 output.errorMessage = "$deviceInfo: failed in 'get' command. Message: ${e.message}..."
85 log.error("$deviceInfo: failed in 'get' command. Exception: $e")
90 override fun getConfig(filter: String, configTarget: String): DeviceResponse {
91 var output = DeviceResponse()
92 val messageId = messageIdInteger.getAndIncrement().toString()
93 log.info("$deviceInfo: getConfig: messageId($messageId)")
95 val message = NetconfMessageUtils.getConfig(messageId, configTarget, filter)
96 output = asyncRpc(message, messageId)
97 } catch (e: Exception) {
98 output.status = RpcStatus.FAILURE
99 output.errorMessage = "$deviceInfo: failed in 'get-config' command. Message: ${e.message}"
100 log.error("$deviceInfo: failed in 'get-config' command. Exception: $e")
105 override fun deleteConfig(configTarget: String): DeviceResponse {
106 var output = DeviceResponse()
107 val messageId = messageIdInteger.getAndIncrement().toString()
108 log.info("$deviceInfo: deleteConfig: messageId($messageId)")
110 val deleteConfigMessage = NetconfMessageUtils.deleteConfig(messageId, configTarget)
111 output.requestMessage = deleteConfigMessage
112 output = asyncRpc(deleteConfigMessage, messageId)
113 } catch (e: Exception) {
114 output.status = RpcStatus.FAILURE
115 output.errorMessage = "$deviceInfo: failed in 'delete-config' command. Message: ${e.message}"
116 log.error("$deviceInfo: failed in 'deleteConfig' command. Exception: $e")
121 override fun lock(configTarget: String): DeviceResponse {
122 var output = DeviceResponse()
123 val messageId = messageIdInteger.getAndIncrement().toString()
124 log.info("$deviceInfo: lock: messageId($messageId)")
126 val lockMessage = NetconfMessageUtils.lock(messageId, configTarget)
127 output.requestMessage = lockMessage
128 output = asyncRpc(lockMessage, messageId)
129 } catch (e: Exception) {
130 output.status = RpcStatus.FAILURE
131 output.errorMessage = "$deviceInfo: failed in 'lock' command. Message ${e.message}"
132 log.error("$deviceInfo: failed in 'lock' command. Exception: $e")
138 override fun unLock(configTarget: String): DeviceResponse {
139 var output = DeviceResponse()
140 val messageId = messageIdInteger.getAndIncrement().toString()
141 log.info("$deviceInfo: unLock: messageId($messageId)")
143 val unlockMessage = NetconfMessageUtils.unlock(messageId, configTarget)
144 output.requestMessage = unlockMessage
145 output = asyncRpc(unlockMessage, messageId)
146 } catch (e: Exception) {
147 output.status = RpcStatus.FAILURE
148 output.errorMessage = "$deviceInfo: failed in 'unLock' command. Message: ${e.message}"
149 log.error("$deviceInfo: failed in 'unLock' command. Exception: $e")
154 override fun commit(confirmed: Boolean, confirmTimeout: Int, persist: String, persistId: String): DeviceResponse {
155 var output = DeviceResponse()
156 val messageId = messageIdInteger.getAndIncrement().toString()
157 log.info("$deviceInfo: commit: messageId($messageId)")
159 val messageContent = NetconfMessageUtils.commit(messageId, confirmed, confirmTimeout, persist, persistId)
160 output = asyncRpc(messageContent, messageId)
161 } catch (e: Exception) {
162 output.status = RpcStatus.FAILURE
163 output.errorMessage = "$deviceInfo: failed in 'commit' command. Message: ${e.message}"
164 log.error("$deviceInfo: failed in 'commit' command. Exception: $e")
169 override fun cancelCommit(persistId: String): DeviceResponse {
170 var output = DeviceResponse()
171 val messageId = messageIdInteger.getAndIncrement().toString()
172 log.info("$deviceInfo: cancelCommit: messageId($messageId)")
174 val messageContent = NetconfMessageUtils.cancelCommit(messageId, persistId)
175 output = asyncRpc(messageContent, messageId)
176 } catch (e: Exception) {
177 output.status = RpcStatus.FAILURE
178 output.errorMessage = "$deviceInfo: failed in 'cancelCommit' command. Message: ${e.message}"
179 log.error("$deviceInfo: failed in 'cancelCommit' command. Exception: $e")
184 override fun discardConfig(): DeviceResponse {
185 var output = DeviceResponse()
186 val messageId = messageIdInteger.getAndIncrement().toString()
187 log.info("$deviceInfo: discard: messageId($messageId)")
189 val discardChangesMessage = NetconfMessageUtils.discardChanges(messageId)
190 output.requestMessage = discardChangesMessage
191 output = asyncRpc(discardChangesMessage, messageId)
192 } catch (e: Exception) {
193 output.status = RpcStatus.FAILURE
194 output.errorMessage = "$deviceInfo: failed in 'discard-config' command. Message: ${e.message}"
195 log.error("$deviceInfo: failed in 'discard-config' command. Exception: $e")
200 override fun editConfig(messageContent: String, configTarget: String,
201 editDefaultOperation: String): DeviceResponse {
202 var response = DeviceResponse()
203 val messageId = messageIdInteger.getAndIncrement().toString()
204 log.info("$deviceInfo: editConfig: messageId($messageId)")
207 NetconfMessageUtils.editConfig(messageId, configTarget, editDefaultOperation, messageContent)
208 response.requestMessage = editMessage
209 response = asyncRpc(editMessage, messageId)
210 } catch (e: Exception) {
211 response.status = RpcStatus.FAILURE
212 response.errorMessage = "$deviceInfo: failed in 'editConfig' command. Message: ${e.message}"
213 log.error("$deviceInfo: failed in 'editConfig' command. Exception: $e")
218 override fun validate(configTarget: String): DeviceResponse {
219 var output = DeviceResponse()
220 val messageId = messageIdInteger.getAndIncrement().toString()
222 val validateMessage = NetconfMessageUtils.validate(messageId, configTarget)
223 output.requestMessage = validateMessage
224 output = asyncRpc(validateMessage, messageId)
225 } catch (e: Exception) {
226 output.status = RpcStatus.FAILURE
227 output.errorMessage = "$deviceInfo: failed in 'validate' command. Message: ${e.message}"
228 log.error("$deviceInfo: failed in 'validate' command. Exception: $e")
233 override fun closeSession(force: Boolean): DeviceResponse {
234 var output = DeviceResponse()
235 val messageId = messageIdInteger.getAndIncrement().toString()
236 log.info("$deviceInfo: closeSession: messageId($messageId)")
238 val messageContent = NetconfMessageUtils.closeSession(messageId, force)
239 output = asyncRpc(messageContent, messageId)
240 } catch (e: Exception) {
241 output.status = RpcStatus.FAILURE
242 output.errorMessage = "$deviceInfo: failed in 'closeSession' command. Message: ${e.message}"
243 log.error("$deviceInfo: failed in 'closeSession' command. Exception: $e")
248 @Throws(NetconfException::class)
249 override fun asyncRpc(request: String, messageId: String): DeviceResponse {
250 val response = DeviceResponse()
251 log.info("$deviceInfo: send asyncRpc with messageId($messageId)")
252 response.requestMessage = request
254 val rpcResponse = netconfSession.asyncRpc(request, messageId).get(responseTimeout.toLong(), TimeUnit.SECONDS)
255 //TODO catch TimeoutException and ExecutionException
256 if (!NetconfMessageUtils.checkReply(rpcResponse)) {
257 log.error("RPC response didn't pass validation... $rpcResponse")
258 throw NetconfException(rpcResponse)
260 response.responseMessage = rpcResponse
261 response.status = RpcStatus.SUCCESS
262 response.errorMessage = null