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