2e33b9aa2a78a68e4ff2e4b9ae86245fe4f729ad
[ccsdk/cds.git] /
1 /*
2  * Copyright © 2017-2019 AT&T, Bell Canada
3  * Modifications Copyright (c) 2019 IBM, Bell Canada
4  *
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
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17
18 package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.core
19
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
26
27 class NetconfRpcServiceImpl(private var deviceInfo: DeviceInfo) : NetconfRpcService {
28
29     private val log = LoggerFactory.getLogger(NetconfRpcService::class.java)
30
31     private var responseTimeout: Int = deviceInfo.replyTimeout
32
33     private lateinit var netconfSession: NetconfSession
34
35     private val messageIdInteger = AtomicInteger(1)
36
37     fun setNetconfSession(netconfSession: NetconfSession) {
38         this.netconfSession = netconfSession
39     }
40
41     /**
42      * accept a user-supplied RPC message WITH HEADER
43      * <rpc message-id="abc123" xmlns=".....">
44      *     .....
45      *     .....
46      * </rpc>
47      *
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.
54      */
55     private fun replaceUserSuppliedNetconfMessageID(rpc: String, updatedMessageID: String): String {
56         return rpc.replaceFirst("message-id=\".+\"".toRegex(), "message-id=\"$updatedMessageID\"")
57     }
58
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)")
65         try {
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")
71         }
72         return output
73     }
74
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)")
79         try {
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")
86         }
87         return output
88     }
89
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)")
94         try {
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")
101         }
102         return output
103     }
104
105     override fun deleteConfig(configTarget: String): DeviceResponse {
106         var output = DeviceResponse()
107         val messageId = messageIdInteger.getAndIncrement().toString()
108         log.info("$deviceInfo: deleteConfig: messageId($messageId)")
109         try {
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")
117         }
118         return output
119     }
120
121     override fun lock(configTarget: String): DeviceResponse {
122         var output = DeviceResponse()
123         val messageId = messageIdInteger.getAndIncrement().toString()
124         log.info("$deviceInfo: lock: messageId($messageId)")
125         try {
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")
133         }
134
135         return output
136     }
137
138     override fun unLock(configTarget: String): DeviceResponse {
139         var output = DeviceResponse()
140         val messageId = messageIdInteger.getAndIncrement().toString()
141         log.info("$deviceInfo: unLock: messageId($messageId)")
142         try {
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")
150         }
151         return output
152     }
153
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)")
158         try {
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")
165         }
166         return output
167     }
168
169     override fun cancelCommit(persistId: String): DeviceResponse {
170         var output = DeviceResponse()
171         val messageId = messageIdInteger.getAndIncrement().toString()
172         log.info("$deviceInfo: cancelCommit: messageId($messageId)")
173         try {
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")
180         }
181         return output
182     }
183
184     override fun discardConfig(): DeviceResponse {
185         var output = DeviceResponse()
186         val messageId = messageIdInteger.getAndIncrement().toString()
187         log.info("$deviceInfo: discard: messageId($messageId)")
188         try {
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")
196         }
197         return output
198     }
199
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)")
205         try {
206             val editMessage =
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")
214         }
215         return response
216     }
217
218     override fun validate(configTarget: String): DeviceResponse {
219         var output = DeviceResponse()
220         val messageId = messageIdInteger.getAndIncrement().toString()
221         try {
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")
229         }
230         return output
231     }
232
233     override fun closeSession(force: Boolean): DeviceResponse {
234         var output = DeviceResponse()
235         val messageId = messageIdInteger.getAndIncrement().toString()
236         log.info("$deviceInfo: closeSession: messageId($messageId)")
237         try {
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")
244         }
245         return output
246     }
247
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
253
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)
259         }
260         response.responseMessage = rpcResponse
261         response.status = RpcStatus.SUCCESS
262         response.errorMessage = null
263         return response
264     }
265 }