0e264bcb9953ff69ef479932fb9cbb311fe798ff
[ccsdk/cds.git] /
1 /*
2  * Copyright © 2017-2018 AT&T Intellectual Property.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor
18
19 import org.apache.commons.collections.CollectionUtils
20 import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.core.NetconfSessionFactory
21 import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.data.DeviceResponse
22 import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.data.NetconfAdaptorConstant
23 import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.interfaces.DeviceInfo
24 import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.interfaces.NetconfRpcClientService
25 import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.interfaces.NetconfSession
26 import org.onap.ccsdk.apps.blueprintsprocessor.functions.netconf.executor.utils.RpcMessageUtils
27 import org.slf4j.LoggerFactory
28 import org.springframework.beans.factory.config.ConfigurableBeanFactory
29 import org.springframework.context.annotation.Scope
30 import org.springframework.stereotype.Service
31 import java.util.*
32 import java.util.concurrent.TimeUnit
33
34
35 @Service("netconf-rpc-service")
36 @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
37 class NetconfRpcService : NetconfRpcClientService {
38
39     val log = LoggerFactory.getLogger(NetconfRpcService::class.java)
40
41     lateinit var deviceInfo: DeviceInfo
42     lateinit var netconfSession: NetconfSession
43
44     private val applyConfigIds = ArrayList<String>()
45     private val recordedApplyConfigIds = ArrayList<String>()
46     private val DEFAULT_MESSAGE_TIME_OUT = 30
47
48
49     override fun connect(deviceInfo: DeviceInfo): NetconfSession {
50         try {
51
52             this.deviceInfo = deviceInfo
53
54             log.info("Connecting Netconf Device .....")
55             this.netconfSession = NetconfSessionFactory.instance("DEFAULT_NETCONF_SESSION", deviceInfo)
56             publishMessage("Netconf Device Connection Established")
57             return this.netconfSession
58         } catch (e: NetconfException) {
59             publishMessage(String.format("Netconf Device Connection Failed, %s", e.message))
60             throw NetconfException("Netconf Device Connection Failed,$deviceInfo",e)
61         }
62     }
63
64     override  fun disconnect() {
65         netconfSession.close()
66     }
67
68     override fun reconnect() {
69         disconnect()
70         connect(deviceInfo)
71     }
72
73     override fun getConfig(messageId: String, messageContent: String, configTarget: String, messageTimeout: Int): DeviceResponse {
74         var output = DeviceResponse()
75         log.info("in the NetconfRpcService "+messageId)
76         try {
77             val message = RpcMessageUtils.getConfig(messageId, configTarget, messageContent)
78             output = asyncRpc(message, messageId, messageTimeout)
79         } catch (e: Exception) {
80             output.status = NetconfAdaptorConstant.STATUS_FAILURE
81             output.errorMessage = e.message
82         }
83
84         return output
85     }
86
87     override fun deleteConfig(messageId: String, configTarget: String, messageTimeout: Int): DeviceResponse {
88         var output = DeviceResponse()
89         try {
90             val deleteConfigMessage = RpcMessageUtils.deleteConfig(messageId, configTarget)
91             output.requestMessage = deleteConfigMessage
92             output = asyncRpc(deleteConfigMessage, messageId, messageTimeout)
93         } catch (e: Exception) {
94             output.status = NetconfAdaptorConstant.STATUS_FAILURE
95             output.errorMessage = "failed in delete config command " + e.message
96         }
97
98         return output
99     }
100
101     override fun lock(messageId: String, configTarget: String, messageTimeout: Int): DeviceResponse {
102         var output = DeviceResponse()
103         try {
104             val lockMessage = RpcMessageUtils.lock(messageId, configTarget)
105             output.requestMessage = lockMessage
106             output = asyncRpc(lockMessage, messageId, messageTimeout)
107         } catch (e: Exception) {
108             output.status = NetconfAdaptorConstant.STATUS_FAILURE
109             output.errorMessage = "failed in lock command " + e.message
110         }
111
112         return output
113     }
114
115     override fun unLock(messageId: String, configTarget: String, messageTimeout: Int): DeviceResponse {
116         var output = DeviceResponse()
117         try {
118             val unlockMessage = RpcMessageUtils.unlock(messageId, configTarget)
119             output.requestMessage = unlockMessage
120             output = asyncRpc(unlockMessage, messageId, messageTimeout)
121         } catch (e: Exception) {
122             output.status = NetconfAdaptorConstant.STATUS_FAILURE
123             output.errorMessage = "failed in lock command " + e.message
124         }
125
126         return output
127     }
128
129     override fun commit(messageId: String, message: String, discardChanges: Boolean, messageTimeout: Int): DeviceResponse {
130         var output = DeviceResponse()
131         try {
132             val messageContent = RpcMessageUtils.commit(messageId, message)
133             output = asyncRpc(messageContent, messageId, messageTimeout)
134         } catch (e: Exception) {
135             output.status = NetconfAdaptorConstant.STATUS_FAILURE
136             output.errorMessage = "failed in commit command " + e.message
137         } finally {
138             // Update the Apply Config status
139             if (CollectionUtils.isNotEmpty(applyConfigIds)) {
140                 val status = if (NetconfAdaptorConstant.STATUS_SUCCESS.equals(output.status,ignoreCase = true))
141                     NetconfAdaptorConstant.CONFIG_STATUS_SUCCESS
142                 else
143                     NetconfAdaptorConstant.CONFIG_STATUS_FAILED
144
145                 applyConfigIds.forEach{
146                     recordedApplyConfigIds.add(it)
147                     try {
148                         //TODO persistance logic
149                        // configPersistService.updateApplyConfig(applyConfigId, status)
150                     } catch (e: Exception) {
151                         log.error("failed to update apply config ($it) status ($status)")
152                     }
153
154                 }
155                 applyConfigIds.clear()
156             }
157             // TODO
158             // Update the Configuration in Running Config Table from 1810 release
159             // String recordMessageId = "recoded-running-config-" + messageId;
160             // recordRunningConfig(recordMessageId, null);
161         }
162
163         // If commit failed apply discard changes
164         if (discardChanges && NetconfAdaptorConstant.STATUS_FAILURE.equals(output.status,ignoreCase = true)) {
165             try {
166                 val discardChangesConfigMessageId = "$messageId-discard-changes"
167                 discardConfig(discardChangesConfigMessageId, NetconfAdaptorConstant.DEFAULT_MESSAGE_TIME_OUT)
168             } catch (e: Exception) {
169                 log.error("failed to rollback ($e) ")
170             }
171
172         }
173
174         return output
175     }
176     override fun discardConfig(messageId: String, messageTimeout: Int): DeviceResponse {
177         var output = DeviceResponse()
178         try {
179             val discardChangesMessage = RpcMessageUtils.discardChanges(messageId)
180             output.requestMessage = discardChangesMessage
181             output = asyncRpc(discardChangesMessage, messageId, messageTimeout)
182         } catch (e: Exception) {
183             output.status = NetconfAdaptorConstant.STATUS_FAILURE
184             output.errorMessage = "failed in discard changes command " + e.message
185         }
186
187         return output
188     }
189
190     override fun close(messageId: String, force: Boolean, messageTimeout: Int): DeviceResponse {
191         var output = DeviceResponse()
192         try {
193             val messageContent = RpcMessageUtils.closeSession(messageId, force)
194             output = asyncRpc(messageContent, messageId, messageTimeout)
195         } catch (e: Exception) {
196             output.status = NetconfAdaptorConstant.STATUS_FAILURE
197             output.responseMessage = "failed in close command " + e.message
198         }
199
200         return output
201     }
202
203
204     override fun asyncRpc(request: String, msgId: String, timeOut: Int): DeviceResponse {
205         val response = DeviceResponse()
206                 try {
207             recordMessage("RPC request $request")
208             response.requestMessage = request
209             publishMessage("Netconf RPC InProgress")
210
211             val rpcResponse = netconfSession.asyncRpc(request, msgId).get(timeOut.toLong(), TimeUnit.SECONDS)
212             response.responseMessage = rpcResponse
213
214             if (!RpcMessageUtils.checkReply(rpcResponse)) {
215                 throw NetconfException(rpcResponse)
216             }
217             response.status = NetconfAdaptorConstant.STATUS_SUCCESS
218             response.errorMessage = null
219         } catch (e: Exception) {
220             response.status = NetconfAdaptorConstant.STATUS_FAILURE
221             response.errorMessage = e.message
222         } finally {
223             recordMessage(String.format("RPC Response status (%s) reply (%s), error message (%s)", response.status,
224                     response.responseMessage, response.errorMessage))
225
226               when {
227                    NetconfAdaptorConstant.STATUS_FAILURE.equals(response.status,ignoreCase = true) -> publishMessage(String.format("Netconf RPC Failed for messgaeID (%s) with (%s)", msgId,
228                            response.errorMessage))
229                    else -> publishMessage(String.format("Netconf RPC Success for messgaeID (%s)", msgId))
230                }
231         }
232
233         return response
234     }
235
236     override fun editConfig(messageId: String, messageContent: String, reConnect: Boolean, wait: Int, lock: Boolean, configTarget: String, editDefaultOperation: String, clearCandidate: Boolean, validate: Boolean, commit: Boolean, discardChanges: Boolean, unlock: Boolean, preRestartWait: Int, postRestartWait: Int, messageTimeout: Int): DeviceResponse {
237         var editConfigDeviceResponse = DeviceResponse()
238
239         try {
240             val editMessage = RpcMessageUtils.editConfig(messageId, NetconfAdaptorConstant.CONFIG_TARGET_CANDIDATE,
241                     editDefaultOperation, messageContent)
242             editConfigDeviceResponse.requestMessage = editMessage
243
244            /* val applyConfigId = configPersistService.saveApplyConfig(netconfExecutionRequest.getRequestId(),
245                     netconfDeviceInfo.getName(), netconfDeviceInfo.getDeviceId(), ConfigModelConstant.PROTOCOL_NETCONF,
246                     configTarget, editMessage)
247
248             applyConfigIds.add(applyConfigId)  */
249
250             // Reconnect Client Session
251             if (reConnect) {
252                 reconnect()
253             }
254             // Provide invocation Delay
255             if (wait > 0) {
256                 log.info("Waiting for {} sec for the transaction to start", wait)
257                 Thread.sleep(wait * 1000L)
258             }
259
260             if (lock) {
261                 val lockMessageId = "$messageId-lock"
262                 val lockDeviceResponse = lock(lockMessageId, configTarget, DEFAULT_MESSAGE_TIME_OUT)
263                 editConfigDeviceResponse.addSubDeviceResponse(lockMessageId, lockDeviceResponse)
264                 if (!NetconfAdaptorConstant.STATUS_SUCCESS.equals(lockDeviceResponse.status,ignoreCase = true)) {
265                     throw NetconfException(lockDeviceResponse.errorMessage!!)
266                 }
267             }
268
269             if (clearCandidate) {
270                 val deleteConfigMessageId = "$messageId-delete"
271                 val deleteConfigDeviceResponse = deleteConfig(deleteConfigMessageId,
272                         NetconfAdaptorConstant.CONFIG_TARGET_CANDIDATE, DEFAULT_MESSAGE_TIME_OUT)
273                 editConfigDeviceResponse.addSubDeviceResponse(deleteConfigMessageId, deleteConfigDeviceResponse)
274                 if (!NetconfAdaptorConstant.STATUS_SUCCESS.equals(deleteConfigDeviceResponse.status,ignoreCase = true)) {
275                     throw NetconfException(deleteConfigDeviceResponse.errorMessage!!)
276                 }
277             }
278
279             if (discardChanges) {
280                 val discardConfigMessageId = "$messageId-discard"
281                 val discardConfigDeviceResponse = discardConfig(discardConfigMessageId, DEFAULT_MESSAGE_TIME_OUT)
282                 editConfigDeviceResponse.addSubDeviceResponse(discardConfigMessageId, discardConfigDeviceResponse)
283                 if (!NetconfAdaptorConstant.STATUS_SUCCESS.equals(discardConfigDeviceResponse.status,ignoreCase = true)) {
284                     throw NetconfException(discardConfigDeviceResponse.errorMessage!!)
285                 }
286             }
287
288             editConfigDeviceResponse = asyncRpc(editMessage, messageId, messageTimeout)
289             if (!NetconfAdaptorConstant.STATUS_SUCCESS.equals(editConfigDeviceResponse.status,ignoreCase = true)) {
290                 throw NetconfException(editConfigDeviceResponse.errorMessage!!)
291             }
292
293             if (validate) {
294                 val validateMessageId = "$messageId-validate"
295                 val validateDeviceResponse = validate(validateMessageId,
296                         NetconfAdaptorConstant.CONFIG_TARGET_CANDIDATE, DEFAULT_MESSAGE_TIME_OUT)
297                 editConfigDeviceResponse.addSubDeviceResponse(validateMessageId, validateDeviceResponse)
298                 if (!NetconfAdaptorConstant.STATUS_SUCCESS.equals(validateDeviceResponse.status,ignoreCase = true)) {
299                     throw NetconfException(validateDeviceResponse.errorMessage!!)
300                 }
301             }
302
303             /**
304              * If Commit is enable, the commit response is treated as Edit config response, If commit failed, we
305              * need not to throw an exception, until we unlock the device.
306              */
307             if (commit) {
308                 val commitMessageId = "$messageId-commit"
309                 val commitDeviceResponse = commit(commitMessageId, commitMessageId, discardChanges, DEFAULT_MESSAGE_TIME_OUT)
310                 editConfigDeviceResponse.addSubDeviceResponse(commitMessageId, commitDeviceResponse)
311                 if (!NetconfAdaptorConstant.STATUS_SUCCESS.equals(commitDeviceResponse.status,ignoreCase = true)) {
312                     throw NetconfException(commitDeviceResponse.errorMessage!!)
313                 }
314             }
315
316             // Provide pre restart Delay
317             if (preRestartWait > 0) {
318                 log.info("Waiting for {} sec for restart", wait)
319                 Thread.sleep(preRestartWait * 1000L)
320             }
321             // TODO Restart Device
322             // Provide post restart Delay
323             if (postRestartWait > 0) {
324                 log.info("Waiting for {} sec for the post restart", wait)
325                 Thread.sleep(postRestartWait * 1000L)
326             }
327
328         } catch (e: Exception) {
329             editConfigDeviceResponse.status = NetconfAdaptorConstant.STATUS_FAILURE
330             editConfigDeviceResponse.errorMessage = e.message
331         } finally {
332             if (unlock) {
333                 val unlockMessageId = "$messageId-unlock"
334                 val unlockDeviceResponse = unLock(unlockMessageId, configTarget, DEFAULT_MESSAGE_TIME_OUT)
335                 editConfigDeviceResponse.addSubDeviceResponse(unlockMessageId, unlockDeviceResponse)
336                 if (!NetconfAdaptorConstant.STATUS_SUCCESS.equals(unlockDeviceResponse.status,ignoreCase = true)) {
337                     editConfigDeviceResponse.status = NetconfAdaptorConstant.STATUS_FAILURE
338                     editConfigDeviceResponse.errorMessage = unlockDeviceResponse.errorMessage
339                 }
340             }
341         }
342         return editConfigDeviceResponse
343     }
344
345     override fun validate(messageId: String, configTarget: String, messageTimeout: Int): DeviceResponse {
346         var output = DeviceResponse()
347         try {
348             val validateMessage = RpcMessageUtils.validate(messageId, configTarget)
349             output.requestMessage = validateMessage
350             output = asyncRpc(validateMessage, messageId, messageTimeout)
351         } catch (e: Exception) {
352             output.status = NetconfAdaptorConstant.STATUS_FAILURE
353             output.errorMessage = "failed in validate command " + e.message
354         }
355
356         return output
357     }
358
359
360     fun recordMessage(message: String) {
361         recordMessage(NetconfAdaptorConstant.LOG_MESSAGE_TYPE_LOG, message)
362     }
363
364     fun recordMessage(messageType: String, message: String) {
365         //TODO
366         //eventPublishService.recordMessage(netconfExecutionRequest.getRequestId(), messageType, message)
367     }
368
369     fun publishMessage(message: String) {
370         //TODO
371         //eventPublishService.publishMessage(netconfExecutionRequest.getRequestId(), message)
372     }
373
374
375 }