2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Modifications Copyright (c) 2019 Samsung
8 * ================================================================================
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
22 package org.onap.so.bpmn.infrastructure.scripts
24 import org.camunda.bpm.engine.delegate.BpmnError
25 import org.camunda.bpm.engine.delegate.DelegateExecution
26 import org.onap.appc.client.lcm.model.Action
27 import org.onap.appc.client.lcm.model.ActionIdentifiers
28 import org.onap.appc.client.lcm.model.Flags
29 import org.onap.appc.client.lcm.model.Status
30 import org.onap.logging.filter.base.ErrorCode
31 import org.onap.so.bpmn.common.scripts.ExceptionUtil
32 import org.onap.so.bpmn.common.scripts.MsoUtils
33 import org.onap.so.bpmn.core.json.JsonUtils
34 import org.onap.aaiclient.client.aai.*
35 import org.onap.aaiclient.client.aai.entities.AAIResultWrapper
36 import org.onap.aaiclient.client.aai.entities.uri.AAIResourceUri
37 import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory
38 import org.onap.so.client.appc.ApplicationControllerClient
39 import org.onap.so.client.appc.ApplicationControllerSupport
40 import org.onap.so.logger.LoggingAnchor
41 import org.onap.so.logger.MessageEnum
42 import org.slf4j.Logger
43 import org.slf4j.LoggerFactory
44 import groovy.json.JsonOutput
45 import groovy.json.JsonSlurper
47 public class VnfInPlaceUpdate extends VnfCmBase {
48 private static final Logger logger = LoggerFactory.getLogger(VnfInPlaceUpdate.class)
50 ExceptionUtil exceptionUtil = new ExceptionUtil()
51 JsonUtils jsonUtils = new JsonUtils()
52 def prefix = "VnfIPU_"
55 * Initialize the flow's variables.
57 * @param execution The flow's execution instance.
59 public void initProcessVariables(DelegateExecution execution) {
60 execution.setVariable('prefix', 'VnfIPU_')
61 execution.setVariable('Request', null)
62 execution.setVariable('requestInfo', null)
63 execution.setVariable('source', null)
64 execution.setVariable('vnfInputs', null)
65 execution.setVariable('tenantId', null)
66 execution.setVariable('vnfParams', null)
67 execution.setVariable('controllerType', null)
68 execution.setVariable('UpdateVnfSuccessIndicator', false)
69 execution.setVariable('serviceType', null)
70 execution.setVariable('nfRole', null)
71 execution.setVariable('currentActivity', 'VnfIPU')
72 execution.setVariable('workStep', null)
73 execution.setVariable('failedActivity', null)
74 execution.setVariable('errorCode', "0")
75 execution.setVariable('errorText', null)
76 execution.setVariable('healthCheckIndex0', 0)
77 execution.setVariable('healthCheckIndex1', 1)
78 execution.setVariable('maxRetryCount', 3)
79 execution.setVariable("rollbackSetClosedLoopDisabledFlag", false)
80 execution.setVariable("rollbackVnfStop", false)
81 execution.setVariable("rollbackVnfLock", false)
82 execution.setVariable("rollbackQuiesceTraffic", false)
83 execution.setVariable("rollbackSetVnfInMaintenanceFlag", false)
87 * Check for missing elements in the received request.
89 * @param execution The flow's execution instance.
91 public void preProcessRequest(DelegateExecution execution) {
92 def method = getClass().getSimpleName() + '.preProcessRequest(' +
93 'execution=' + execution.getId() +
95 initProcessVariables(execution)
97 logger.trace('Entered {}', method)
99 initProcessVariables(execution)
101 def incomingRequest = execution.getVariable('bpmnRequest')
103 logger.debug("Incoming Infra Request: {}", incomingRequest)
105 def jsonSlurper = new JsonSlurper()
106 def jsonOutput = new JsonOutput()
107 Map reqMap = jsonSlurper.parseText(incomingRequest)
108 logger.debug(" Request is in JSON format.")
110 def serviceInstanceId = execution.getVariable('serviceInstanceId')
111 def vnfId = execution.getVariable('vnfId')
113 execution.setVariable('serviceInstanceId', serviceInstanceId)
114 execution.setVariable('vnfId', vnfId)
115 execution.setVariable("isVidRequest", "true")
116 execution.setVariable('serviceType', 'Mobility')
117 execution.setVariable('payload', "")
118 execution.setVariable('actionSnapshot', Action.Snapshot)
119 execution.setVariable('actionLock', Action.Lock)
120 execution.setVariable('actionUnlock', Action.Unlock)
121 execution.setVariable('actionUpgradePreCheck', Action.UpgradePreCheck)
122 execution.setVariable('actionUpgradePostCheck', Action.UpgradePostCheck)
123 execution.setVariable('actionQuiesceTraffic', Action.QuiesceTraffic)
124 execution.setVariable('actionUpgradeBackup', Action.UpgradeBackup)
125 execution.setVariable('actionUpgradeSoftware', Action.UpgradeSoftware)
126 execution.setVariable('actionResumeTraffic', Action.ResumeTraffic)
129 def controllerType = reqMap.requestDetails?.requestParameters?.controllerType
130 execution.setVariable('controllerType', controllerType)
132 logger.debug('Controller Type: {}', controllerType)
134 def payload = reqMap.requestDetails?.requestParameters?.payload
135 execution.setVariable('payload', payload)
137 logger.debug('Processed payload: {}', payload)
139 def requestId = execution.getVariable("mso-request-id")
140 execution.setVariable('requestId', requestId)
141 execution.setVariable('msoRequestId', requestId)
143 def requestorId = reqMap.requestDetails?.requestInfo?.requestorId ?: null
144 execution.setVariable('requestorId', requestorId)
146 def cloudConfiguration = reqMap.requestDetails?.cloudConfiguration
147 def lcpCloudRegionId = cloudConfiguration.lcpCloudRegionId
148 execution.setVariable('lcpCloudRegionId', lcpCloudRegionId)
149 def cloudOwner = cloudConfiguration.cloudOwner
150 execution.setVariable('cloudOwner', cloudOwner)
151 def tenantId = cloudConfiguration.tenantId
152 execution.setVariable('tenantId', tenantId)
154 execution.setVariable("UpdateVnfInfraSuccessIndicator", false)
158 def source = reqMap.requestDetails?.requestInfo?.source
159 execution.setVariable("source", source)
161 //For Completion Handler & Fallout Handler
163 """<request-info xmlns="http://org.onap/so/infra/vnf-request/v1">
164 <request-id>${MsoUtils.xmlEscape(requestId)}</request-id>
165 <action>UPDATE</action>
166 <source>${MsoUtils.xmlEscape(source)}</source>
169 execution.setVariable("requestInfo", requestInfo)
171 logger.debug('RequestInfo: {}', execution.getVariable("requestInfo"))
173 logger.trace('Exited {}', method)
176 catch(groovy.json.JsonException je) {
177 logger.debug(" Request is not in JSON format.")
178 exceptionUtil.buildAndThrowWorkflowException(execution, 5000, "Invalid request format")
181 String restFaultMessage = e.getMessage()
182 logger.error("{} {} Exception Encountered - {} \n ", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
183 ErrorCode.UnknownError.getValue(), restFaultMessage, e)
184 exceptionUtil.buildAndThrowWorkflowException(execution, 5000, restFaultMessage)
189 * Prepare and send the sychronous response for this flow.
191 * @param execution The flow's execution instance.
193 public void sendSynchResponse(DelegateExecution execution) {
194 def method = getClass().getSimpleName() + '.sendSynchResponse(' +
195 'execution=' + execution.getId() +
198 logger.trace('Entered {}', method)
201 def requestInfo = execution.getVariable('requestInfo')
202 def requestId = execution.getVariable('requestId')
203 def source = execution.getVariable('source')
204 def progress = getNodeTextForce(requestInfo, 'progress')
205 if (progress.isEmpty()) {
208 def startTime = getNodeTextForce(requestInfo, 'start-time')
209 if (startTime.isEmpty()) {
210 startTime = System.currentTimeMillis()
213 // RESTResponse (for API Handler (APIH) Reply Task)
214 def vnfId = execution.getVariable("vnfId")
215 String synchResponse = """{"requestReferences":{"instanceId":"${vnfId}","requestId":"${requestId}"}}""".trim()
217 sendWorkflowResponse(execution, 200, synchResponse)
219 logger.trace('Exited {}', method)
220 } catch (BpmnError e) {
222 } catch (Exception e) {
223 logger.error("{} {} Caught exception in {} \n ", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
224 ErrorCode.UnknownError.getValue(), method, e)
225 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in sendResponse(): ' + e.getMessage())
231 * Check if this VNF is already in maintenance in A&AI.
234 * @param execution The flow's execution instance.
236 public void checkIfVnfInMaintInAAI(DelegateExecution execution) {
237 def method = getClass().getSimpleName() + '.checkIfVnfInMaintInAAI(' +
238 'execution=' + execution.getId() +
241 execution.setVariable('errorCode', "0")
242 execution.setVariable("workStep", "checkIfVnfInMaintInAAI")
243 execution.setVariable("failedActivity", "AAI")
244 logger.trace('Entered {}', method)
247 AAIRestClientImpl client = new AAIRestClientImpl()
248 AAIValidatorImpl aaiValidator = new AAIValidatorImpl()
249 aaiValidator.setClient(client)
250 def vnfId = execution.getVariable("vnfId")
251 boolean isInMaint = aaiValidator.isVNFLocked(vnfId)
252 logger.debug("isInMaint result: {}", isInMaint)
253 execution.setVariable('isVnfInMaintenance', isInMaint)
256 execution.setVariable("errorCode", "1003")
257 execution.setVariable("errorText", "VNF is in maintenance in A&AI")
261 logger.trace('Exited {}', method)
262 } catch (BpmnError e) {
264 } catch (Exception e) {
265 logger.error("{} {} Caught exception in {} \n ", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
266 ErrorCode.UnknownError.getValue(), method, e)
267 execution.setVariable("errorCode", "1002")
268 execution.setVariable("errorText", e.getMessage())
269 //exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in checkIfVnfInMaintInAAI(): ' + e.getMessage())
275 * Check if this VNF's pservers are locked in A&AI.
278 * @param execution The flow's execution instance.
280 public void checkIfPserversInMaintInAAI(DelegateExecution execution) {
281 def method = getClass().getSimpleName() + '.checkIfPserversInMaintInAAI(' +
282 'execution=' + execution.getId() +
285 execution.setVariable('errorCode', "0")
286 logger.trace('Entered {}', method)
287 execution.setVariable("workStep", "checkIfPserversInMaintInAAI")
288 execution.setVariable("failedActivity", "AAI")
291 AAIRestClientImpl client = new AAIRestClientImpl()
292 AAIValidatorImpl aaiValidator = new AAIValidatorImpl()
293 aaiValidator.setClient(client)
294 def vnfId = execution.getVariable("vnfId")
295 boolean areLocked = aaiValidator.isPhysicalServerLocked(vnfId)
296 logger.debug("areLocked result: {}", areLocked)
297 execution.setVariable('arePserversLocked', areLocked)
300 execution.setVariable("errorCode", "1003")
301 execution.setVariable("errorText", "pServers are locked in A&AI")
304 logger.trace('Exited {}', method)
305 } catch (BpmnError e) {
307 } catch (Exception e) {
308 logger.error("{} {} Caught exception in {} \n ", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
309 ErrorCode.UnknownError.getValue(), method, e)
310 execution.setVariable("errorCode", "1002")
311 execution.setVariable("errorText", e.getMessage())
312 //exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in checkIfPserversInMaintInAAI(): ' + e.getMessage())
317 * Set inMaint flag for this VNF to the specified value in A&AI.
320 * @param execution The flow's execution instance.
321 * @param inMaint The boolean value of the flag to set
323 public void setVnfInMaintFlagInAAI(DelegateExecution execution, boolean inMaint) {
324 def method = getClass().getSimpleName() + '.setVnfInMaintFlagInAAI(' +
325 'execution=' + execution.getId() +
328 execution.setVariable('errorCode', "0")
329 logger.trace('Entered {}', method)
331 execution.setVariable("workStep", "setVnfInMaintFlagInAAI")
334 execution.setVariable("workStep", "unsetVnfInMaintFlagInAAI")
336 execution.setVariable("failedActivity", "AAI")
339 AAIRestClientImpl client = new AAIRestClientImpl()
340 AAIUpdatorImpl aaiUpdator = new AAIUpdatorImpl()
341 aaiUpdator.setClient(client)
342 def vnfId = execution.getVariable("vnfId")
344 aaiUpdator.updateVnfToLocked(vnfId)
345 execution.setVariable("rollbackSetVnfInMaintenanceFlag", true)
348 aaiUpdator.updateVnfToUnLocked(vnfId)
351 logger.trace('Exited {}', method)
352 } catch (BpmnError e) {
354 } catch (Exception e) {
355 logger.error(LoggingAnchor.FIVE, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), 'Caught exception in' +
356 ' ' + method, "BPMN", ErrorCode.UnknownError.getValue(), "Exception is:\n" + e);
357 execution.setVariable("errorCode", "1002")
358 execution.setVariable("errorText", e.getMessage())
363 * Check if VF Closed Loop Disabled in A&AI.
366 * @param execution The flow's execution instance.
368 public void checkIfClosedLoopDisabledInAAI(DelegateExecution execution) {
369 def method = getClass().getSimpleName() + '.checkIfClosedLoopDisabledInAAI(' +
370 'execution=' + execution.getId() +
373 execution.setVariable('errorCode', "0")
374 execution.setVariable("workStep", "checkClosedLoopDisabledFlagInAAI")
375 execution.setVariable("failedActivity", "AAI")
376 logger.trace('Entered ' + method)
379 def transactionLoggingUuid = UUID.randomUUID().toString()
380 def vnfId = execution.getVariable("vnfId")
381 logger.debug("vnfId is: " + vnfId)
382 AAIResourcesClient client = new AAIResourcesClient()
383 AAIResourceUri genericVnfUri = AAIUriFactory.createResourceUri(AAIObjectType.GENERIC_VNF, vnfId)
384 AAIResultWrapper aaiRW = client.get(genericVnfUri)
385 Map<String, Object> result = aaiRW.asMap()
386 boolean isClosedLoopDisabled = result.getOrDefault("is-closed-loop-disabled", false)
388 logger.debug("isClosedLoopDisabled result: " + isClosedLoopDisabled)
389 execution.setVariable('isClosedLoopDisabled', isClosedLoopDisabled)
391 if (isClosedLoopDisabled) {
392 execution.setVariable("errorCode", "1004")
393 execution.setVariable("errorText", "closedLoop is disabled in A&AI")
396 logger.trace('Exited ' + method)
397 } catch (BpmnError e) {
399 } catch (Exception e) {
400 logger.error(LoggingAnchor.FIVE, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), 'Caught exception in' +
401 ' ' + method, "BPMN", ErrorCode.UnknownError.getValue(), "Exception is:\n" + e);
402 execution.setVariable("errorCode", "1002")
403 execution.setVariable("errorText", e.getMessage())
408 * Set VF Closed Loop Disabled Flag in A&AI.
411 * @param execution The flow's execution instance.
413 public void setClosedLoopDisabledInAAI(DelegateExecution execution, boolean setDisabled) {
414 def method = getClass().getSimpleName() + '.setClosedLoopDisabledInAAI(' +
415 'execution=' + execution.getId() +
418 execution.setVariable('errorCode', "0")
420 execution.setVariable("workStep", "setClosedLoopDisabledFlagInAAI")
421 execution.setVariable("rollbackSetClosedLoopDisabledFlag", true)
424 execution.setVariable("workStep", "unsetClosedLoopDisabledFlagInAAI")
427 execution.setVariable("failedActivity", "AAI")
428 logger.trace('Entered ' + method)
431 def transactionLoggingUuid = UUID.randomUUID().toString()
432 def vnfId = execution.getVariable("vnfId")
433 AAIResourcesClient client = new AAIResourcesClient()
434 AAIResourceUri genericVnfUri = AAIUriFactory.createResourceUri(AAIObjectType.GENERIC_VNF, vnfId)
436 Map<String, Boolean> request = new HashMap<>()
437 request.put("is-closed-loop-disabled", setDisabled)
438 client.update(genericVnfUri, request)
439 logger.debug("set isClosedLoop to: " + setDisabled)
441 logger.trace('Exited ' + method)
442 } catch (BpmnError e) {
444 } catch (Exception e) {
445 logger.error(LoggingAnchor.FIVE, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), 'Caught exception in' +
446 ' ' + method, "BPMN", ErrorCode.UnknownError.getValue(), "Exception is:\n" + e);
447 execution.setVariable("errorCode", "1002")
448 execution.setVariable("errorText", e.getMessage())
456 * Call APP-C client to execute specified APP-C command for this VNF.
459 * @param execution The flow's execution instance.
460 * @param action The action to take in APP-C.
462 public void runAppcCommand(DelegateExecution execution, Action action) {
463 def method = getClass().getSimpleName() + '.runAppcCommand(' +
464 'execution=' + execution.getId() +
467 execution.setVariable('errorCode', "0")
468 logger.trace('Entered ' + method)
470 ApplicationControllerClient appcClient = null
473 logger.debug("Running APP-C action: " + action.toString())
474 String vnfId = execution.getVariable('vnfId')
475 String msoRequestId = execution.getVariable('requestId')
476 execution.setVariable('msoRequestId', msoRequestId)
477 execution.setVariable("failedActivity", "APP-C")
479 appcClient = new ApplicationControllerClient()
480 ApplicationControllerSupport support = new ApplicationControllerSupport()
481 appcClient.appCSupport=support
482 org.springframework.test.util.ReflectionTestUtils.setField(support, "lcmModelPackage", "org.onap.appc.client.lcm.model");
483 Flags flags = new Flags();
484 ActionIdentifiers actionIdentifiers = new ActionIdentifiers();
485 actionIdentifiers.setVnfId(vnfId);
489 execution.setVariable('workStep', "LockVNF")
490 appcStatus = appcClient.runCommand(Action.Lock,actionIdentifiers,null,msoRequestId)
493 execution.setVariable('workStep', "UnlockVNF")
494 appcStatus = appcClient.runCommand(Action.Unlock,actionIdentifiers,null,msoRequestId)
496 case Action.HealthCheck:
497 def healthCheckIndex = execution.getVariable('healthCheckIndex')
498 execution.setVariable('workStep', "HealthCheckVNF" + healthCheckIndex)
499 execution.setVariable('healthCheckIndex', healthCheckIndex + 1)
500 appcStatus = appcClient.runCommand(Action.HealthCheck,actionIdentifiers,null,msoRequestId)
503 execution.setVariable('workStep', "StartVNF")
504 appcStatus = appcClient.runCommand(Action.Start,actionIdentifiers,null,msoRequestId)
507 execution.setVariable('workStep', "StopVNF")
508 appcStatus = appcClient.runCommand(Action.Stop,actionIdentifiers,null,msoRequestId)
513 logger.debug("Completed AppC request")
514 int appcCode = appcStatus.getCode()
515 logger.debug("AppC status code is: " + appcCode)
516 logger.debug("AppC status message is: " + appcStatus.getMessage())
517 if (support.getCategoryOf(appcStatus) == ApplicationControllerSupport.StatusCategory.ERROR) {
518 execution.setVariable("errorCode", Integer.toString(appcCode))
519 execution.setVariable("errorText", appcStatus.getMessage())
522 logger.trace('Exited ' + method)
523 } catch (BpmnError e) {
524 logger.error(LoggingAnchor.FIVE, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), 'Caught exception in' +
525 ' ' + method, "BPMN", ErrorCode.UnknownError.getValue(), "Exception is:\n" + e);
526 execution.setVariable("errorCode", "1002")
527 execution.setVariable("errorText", e.getMessage())
528 } catch (java.lang.NoSuchMethodError e) {
529 logger.error(LoggingAnchor.FIVE, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), 'Caught exception in' +
530 ' ' + method, "BPMN", ErrorCode.UnknownError.getValue(), "Exception is:\n" + e);
531 execution.setVariable("errorCode", "1002")
532 execution.setVariable("errorText", e.getMessage())
533 } catch (Exception e) {
534 logger.error(LoggingAnchor.FIVE, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), 'Caught exception in' +
535 ' ' + method, "BPMN", ErrorCode.UnknownError.getValue(), "Exception is:\n" + e);
536 execution.setVariable("errorCode", "1002")
537 execution.setVariable("errorText", e.getMessage())
542 * Placeholder for a call to APP-C client to execute specified APP-C command for this VNF.
545 * @param execution The flow's execution instance.
546 * @param action The action to take in APP-C.
548 public void runAppcCommandPlaceholder(DelegateExecution execution, String action) {
549 def method = getClass().getSimpleName() + '.runAppcCommandPlaceholder(' +
550 'execution=' + execution.getId() +
553 execution.setVariable('errorCode', "0")
554 logger.trace('Entered ' + method)
555 execution.setVariable("failedActivity", "APP-C")
556 execution.setVariable("workStep", action)
562 * Handle Abort disposition from RainyDayHandler
564 * @param execution The flow's execution instance.
566 public void abortProcessing(DelegateExecution execution) {
567 def method = getClass().getSimpleName() + '.abortProcessing(' +
568 'execution=' + execution.getId() +
571 logger.trace('Entered ' + method)
573 def errorText = execution.getVariable("errorText")
574 def errorCode = execution.getVariable("errorCode")
576 exceptionUtil.buildAndThrowWorkflowException(execution, errorCode as Integer, errorText)
580 * Increment Retry Count for Current Work Step
582 * @param execution The flow's execution instance.
584 public void incrementRetryCount(DelegateExecution execution) {
585 def method = getClass().getSimpleName() + '.incrementRetryCount(' +
586 'execution=' + execution.getId() +
589 logger.trace('Entered ' + method)
591 String retryCountVariableName = execution.getVariable("workStep") + "RetryCount"
592 execution.setVariable("retryCountVariableName", retryCountVariableName)
594 def retryCountVariable = execution.getVariable(retryCountVariableName)
597 if (retryCountVariable != null) {
598 retryCount = (int) retryCountVariable
603 execution.setVariable(retryCountVariableName, retryCount)
605 logger.debug("value of " + retryCountVariableName + " is " + retryCount)
606 logger.trace('Exited ' + method)