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 groovy.json.JsonOutput
25 import groovy.json.JsonSlurper
26 import org.camunda.bpm.engine.delegate.BpmnError
27 import org.camunda.bpm.engine.delegate.DelegateExecution
28 import org.onap.appc.client.lcm.model.Action
29 import org.onap.appc.client.lcm.model.ActionIdentifiers
30 import org.onap.appc.client.lcm.model.Flags
31 import org.onap.appc.client.lcm.model.Status
32 import org.onap.so.bpmn.common.scripts.ExceptionUtil
33 import org.onap.so.bpmn.common.scripts.MsoUtils
34 import org.onap.so.bpmn.core.json.JsonUtils
35 import org.onap.so.client.aai.*
36 import org.onap.so.client.aai.entities.AAIResultWrapper
37 import org.onap.so.client.aai.entities.uri.AAIUri
38 import org.onap.so.client.aai.entities.uri.AAIUriFactory
39 import org.onap.so.client.appc.ApplicationControllerClient
40 import org.onap.so.client.appc.ApplicationControllerSupport
41 import org.onap.so.logger.MessageEnum
42 import org.onap.so.logger.MsoLogger
43 import org.slf4j.Logger
44 import org.slf4j.LoggerFactory
46 public class VnfInPlaceUpdate extends VnfCmBase {
47 private static final Logger logger = LoggerFactory.getLogger(VnfInPlaceUpdate.class)
49 ExceptionUtil exceptionUtil = new ExceptionUtil()
50 JsonUtils jsonUtils = new JsonUtils()
51 def prefix = "VnfIPU_"
54 * Initialize the flow's variables.
56 * @param execution The flow's execution instance.
58 public void initProcessVariables(DelegateExecution execution) {
59 execution.setVariable('prefix', 'VnfIPU_')
60 execution.setVariable('Request', null)
61 execution.setVariable('requestInfo', null)
62 execution.setVariable('source', null)
63 execution.setVariable('vnfInputs', null)
64 execution.setVariable('tenantId', null)
65 execution.setVariable('vnfParams', null)
66 execution.setVariable('controllerType', null)
67 execution.setVariable('UpdateVnfSuccessIndicator', false)
68 execution.setVariable('serviceType', null)
69 execution.setVariable('nfRole', null)
70 execution.setVariable('currentActivity', 'VnfIPU')
71 execution.setVariable('workStep', null)
72 execution.setVariable('failedActivity', null)
73 execution.setVariable('errorCode', "0")
74 execution.setVariable('errorText', null)
75 execution.setVariable('healthCheckIndex0', 0)
76 execution.setVariable('healthCheckIndex1', 1)
77 execution.setVariable('maxRetryCount', 3)
78 execution.setVariable("rollbackSetClosedLoopDisabledFlag", false)
79 execution.setVariable("rollbackVnfStop", false)
80 execution.setVariable("rollbackVnfLock", false)
81 execution.setVariable("rollbackQuiesceTraffic", false)
82 execution.setVariable("rollbackSetVnfInMaintenanceFlag", false)
86 * Check for missing elements in the received request.
88 * @param execution The flow's execution instance.
90 public void preProcessRequest(DelegateExecution execution) {
91 def method = getClass().getSimpleName() + '.preProcessRequest(' +
92 'execution=' + execution.getId() +
94 initProcessVariables(execution)
96 logger.trace('Entered {}', method)
98 initProcessVariables(execution)
100 def incomingRequest = execution.getVariable('bpmnRequest')
102 logger.debug("Incoming Infra Request: {}", incomingRequest)
104 def jsonSlurper = new JsonSlurper()
105 def jsonOutput = new JsonOutput()
106 Map reqMap = jsonSlurper.parseText(incomingRequest)
107 logger.debug(" Request is in JSON format.")
109 def serviceInstanceId = execution.getVariable('serviceInstanceId')
110 def vnfId = execution.getVariable('vnfId')
112 execution.setVariable('serviceInstanceId', serviceInstanceId)
113 execution.setVariable('vnfId', vnfId)
114 execution.setVariable("isVidRequest", "true")
115 execution.setVariable('serviceType', 'Mobility')
116 execution.setVariable('payload', "")
117 execution.setVariable('actionSnapshot', Action.Snapshot)
118 execution.setVariable('actionLock', Action.Lock)
119 execution.setVariable('actionUnlock', Action.Unlock)
120 execution.setVariable('actionUpgradePreCheck', Action.UpgradePreCheck)
121 execution.setVariable('actionUpgradePostCheck', Action.UpgradePostCheck)
122 execution.setVariable('actionQuiesceTraffic', Action.QuiesceTraffic)
123 execution.setVariable('actionUpgradeBackup', Action.UpgradeBackup)
124 execution.setVariable('actionUpgradeSoftware', Action.UpgradeSoftware)
125 execution.setVariable('actionResumeTraffic', Action.ResumeTraffic)
128 def controllerType = reqMap.requestDetails?.requestParameters?.controllerType
129 execution.setVariable('controllerType', controllerType)
131 logger.debug('Controller Type: {}', controllerType)
133 def payload = reqMap.requestDetails?.requestParameters?.payload
134 execution.setVariable('payload', payload)
136 logger.debug('Processed payload: {}', payload)
138 def requestId = execution.getVariable("mso-request-id")
139 execution.setVariable('requestId', requestId)
140 execution.setVariable('msoRequestId', requestId)
142 def requestorId = reqMap.requestDetails?.requestInfo?.requestorId ?: null
143 execution.setVariable('requestorId', requestorId)
145 def cloudConfiguration = reqMap.requestDetails?.cloudConfiguration
146 def lcpCloudRegionId = cloudConfiguration.lcpCloudRegionId
147 execution.setVariable('lcpCloudRegionId', lcpCloudRegionId)
148 def cloudOwner = cloudConfiguration.cloudOwner
149 execution.setVariable('cloudOwner', cloudOwner)
150 def tenantId = cloudConfiguration.tenantId
151 execution.setVariable('tenantId', tenantId)
153 execution.setVariable("UpdateVnfInfraSuccessIndicator", false)
157 def source = reqMap.requestDetails?.requestInfo?.source
158 execution.setVariable("source", source)
160 //For Completion Handler & Fallout Handler
162 """<request-info xmlns="http://org.onap/so/infra/vnf-request/v1">
163 <request-id>${MsoUtils.xmlEscape(requestId)}</request-id>
164 <action>UPDATE</action>
165 <source>${MsoUtils.xmlEscape(source)}</source>
168 execution.setVariable("requestInfo", requestInfo)
170 logger.debug('RequestInfo: {}', execution.getVariable("requestInfo"))
172 logger.trace('Exited {}', method)
175 catch(groovy.json.JsonException je) {
176 logger.debug(" Request is not in JSON format.")
177 exceptionUtil.buildAndThrowWorkflowException(execution, 5000, "Invalid request format")
180 String restFaultMessage = e.getMessage()
181 logger.error("{} {} {} Exception Encountered - {} \n ", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
182 MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError.getValue(), restFaultMessage, e)
183 exceptionUtil.buildAndThrowWorkflowException(execution, 5000, restFaultMessage)
188 * Prepare and send the sychronous response for this flow.
190 * @param execution The flow's execution instance.
192 public void sendSynchResponse(DelegateExecution execution) {
193 def method = getClass().getSimpleName() + '.sendSynchResponse(' +
194 'execution=' + execution.getId() +
197 logger.trace('Entered {}', method)
200 def requestInfo = execution.getVariable('requestInfo')
201 def requestId = execution.getVariable('requestId')
202 def source = execution.getVariable('source')
203 def progress = getNodeTextForce(requestInfo, 'progress')
204 if (progress.isEmpty()) {
207 def startTime = getNodeTextForce(requestInfo, 'start-time')
208 if (startTime.isEmpty()) {
209 startTime = System.currentTimeMillis()
212 // RESTResponse (for API Handler (APIH) Reply Task)
213 def vnfId = execution.getVariable("vnfId")
214 String synchResponse = """{"requestReferences":{"instanceId":"${vnfId}","requestId":"${requestId}"}}""".trim()
216 sendWorkflowResponse(execution, 200, synchResponse)
218 logger.trace('Exited {}', method)
219 } catch (BpmnError e) {
221 } catch (Exception e) {
222 logger.error("{} {} {} Caught exception in {} \n ", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
223 MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError.getValue(), method, e)
224 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in sendResponse(): ' + e.getMessage())
230 * Check if this VNF is already in maintenance in A&AI.
233 * @param execution The flow's execution instance.
235 public void checkIfVnfInMaintInAAI(DelegateExecution execution) {
236 def method = getClass().getSimpleName() + '.checkIfVnfInMaintInAAI(' +
237 'execution=' + execution.getId() +
240 execution.setVariable('errorCode', "0")
241 execution.setVariable("workStep", "checkIfVnfInMaintInAAI")
242 execution.setVariable("failedActivity", "AAI")
243 logger.trace('Entered {}', method)
246 AAIRestClientImpl client = new AAIRestClientImpl()
247 AAIValidatorImpl aaiValidator = new AAIValidatorImpl()
248 aaiValidator.setClient(client)
249 def vnfId = execution.getVariable("vnfId")
250 boolean isInMaint = aaiValidator.isVNFLocked(vnfId)
251 logger.debug("isInMaint result: {}", isInMaint)
252 execution.setVariable('isVnfInMaintenance', isInMaint)
255 execution.setVariable("errorCode", "1003")
256 execution.setVariable("errorText", "VNF is in maintenance in A&AI")
260 logger.trace('Exited {}', method)
261 } catch (BpmnError e) {
263 } catch (Exception e) {
264 logger.error("{} {} {} Caught exception in {} \n ", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
265 MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError.getValue(), method, e)
266 execution.setVariable("errorCode", "1002")
267 execution.setVariable("errorText", e.getMessage())
268 //exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in checkIfVnfInMaintInAAI(): ' + e.getMessage())
274 * Check if this VNF's pservers are locked in A&AI.
277 * @param execution The flow's execution instance.
279 public void checkIfPserversInMaintInAAI(DelegateExecution execution) {
280 def method = getClass().getSimpleName() + '.checkIfPserversInMaintInAAI(' +
281 'execution=' + execution.getId() +
284 execution.setVariable('errorCode', "0")
285 logger.trace('Entered {}', method)
286 execution.setVariable("workStep", "checkIfPserversInMaintInAAI")
287 execution.setVariable("failedActivity", "AAI")
290 AAIRestClientImpl client = new AAIRestClientImpl()
291 AAIValidatorImpl aaiValidator = new AAIValidatorImpl()
292 aaiValidator.setClient(client)
293 def vnfId = execution.getVariable("vnfId")
294 boolean areLocked = aaiValidator.isPhysicalServerLocked(vnfId)
295 logger.debug("areLocked result: {}", areLocked)
296 execution.setVariable('arePserversLocked', areLocked)
299 execution.setVariable("errorCode", "1003")
300 execution.setVariable("errorText", "pServers are locked in A&AI")
303 logger.trace('Exited {}', method)
304 } catch (BpmnError e) {
306 } catch (Exception e) {
307 logger.error("{} {} {} Caught exception in {} \n ", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
308 MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError.getValue(), method, e)
309 execution.setVariable("errorCode", "1002")
310 execution.setVariable("errorText", e.getMessage())
311 //exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in checkIfPserversInMaintInAAI(): ' + e.getMessage())
316 * Set inMaint flag for this VNF to the specified value in A&AI.
319 * @param execution The flow's execution instance.
320 * @param inMaint The boolean value of the flag to set
322 public void setVnfInMaintFlagInAAI(DelegateExecution execution, boolean inMaint) {
323 def method = getClass().getSimpleName() + '.setVnfInMaintFlagInAAI(' +
324 'execution=' + execution.getId() +
327 execution.setVariable('errorCode', "0")
328 logger.trace('Entered {}', method)
330 execution.setVariable("workStep", "setVnfInMaintFlagInAAI")
333 execution.setVariable("workStep", "unsetVnfInMaintFlagInAAI")
335 execution.setVariable("failedActivity", "AAI")
338 AAIRestClientImpl client = new AAIRestClientImpl()
339 AAIUpdatorImpl aaiUpdator = new AAIUpdatorImpl()
340 aaiUpdator.setClient(client)
341 def vnfId = execution.getVariable("vnfId")
343 aaiUpdator.updateVnfToLocked(vnfId)
344 execution.setVariable("rollbackSetVnfInMaintenanceFlag", true)
347 aaiUpdator.updateVnfToUnLocked(vnfId)
350 logger.trace('Exited {}', method)
351 } catch (BpmnError e) {
353 } catch (Exception e) {
354 logger.error("{} {} {} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError.getValue(), "Exception is:\n" + e);
355 execution.setVariable("errorCode", "1002")
356 execution.setVariable("errorText", e.getMessage())
361 * Check if VF Closed Loop Disabled in A&AI.
364 * @param execution The flow's execution instance.
366 public void checkIfClosedLoopDisabledInAAI(DelegateExecution execution) {
367 def method = getClass().getSimpleName() + '.checkIfClosedLoopDisabledInAAI(' +
368 'execution=' + execution.getId() +
371 execution.setVariable('errorCode', "0")
372 execution.setVariable("workStep", "checkClosedLoopDisabledFlagInAAI")
373 execution.setVariable("failedActivity", "AAI")
374 logger.trace('Entered ' + method)
377 def transactionLoggingUuid = UUID.randomUUID().toString()
378 def vnfId = execution.getVariable("vnfId")
379 logger.debug("vnfId is: " + vnfId)
380 AAIResourcesClient client = new AAIResourcesClient()
381 AAIUri genericVnfUri = AAIUriFactory.createResourceUri(AAIObjectType.GENERIC_VNF, vnfId)
382 AAIResultWrapper aaiRW = client.get(genericVnfUri)
383 Map<String, Object> result = aaiRW.asMap()
384 boolean isClosedLoopDisabled = result.getOrDefault("is-closed-loop-disabled", false)
386 logger.debug("isClosedLoopDisabled result: " + isClosedLoopDisabled)
387 execution.setVariable('isClosedLoopDisabled', isClosedLoopDisabled)
389 if (isClosedLoopDisabled) {
390 execution.setVariable("errorCode", "1004")
391 execution.setVariable("errorText", "closedLoop is disabled in A&AI")
394 logger.trace('Exited ' + method)
395 } catch (BpmnError e) {
397 } catch (Exception e) {
398 logger.error("{} {} {} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError.getValue(), "Exception is:\n" + e);
399 execution.setVariable("errorCode", "1002")
400 execution.setVariable("errorText", e.getMessage())
405 * Set VF Closed Loop Disabled Flag in A&AI.
408 * @param execution The flow's execution instance.
410 public void setClosedLoopDisabledInAAI(DelegateExecution execution, boolean setDisabled) {
411 def method = getClass().getSimpleName() + '.setClosedLoopDisabledInAAI(' +
412 'execution=' + execution.getId() +
415 execution.setVariable('errorCode', "0")
417 execution.setVariable("workStep", "setClosedLoopDisabledFlagInAAI")
418 execution.setVariable("rollbackSetClosedLoopDisabledFlag", true)
421 execution.setVariable("workStep", "unsetClosedLoopDisabledFlagInAAI")
424 execution.setVariable("failedActivity", "AAI")
425 logger.trace('Entered ' + method)
428 def transactionLoggingUuid = UUID.randomUUID().toString()
429 def vnfId = execution.getVariable("vnfId")
430 AAIResourcesClient client = new AAIResourcesClient()
431 AAIUri genericVnfUri = AAIUriFactory.createResourceUri(AAIObjectType.GENERIC_VNF, vnfId)
433 Map<String, Boolean> request = new HashMap<>()
434 request.put("is-closed-loop-disabled", setDisabled)
435 client.update(genericVnfUri, request)
436 logger.debug("set isClosedLoop to: " + setDisabled)
438 logger.trace('Exited ' + method)
439 } catch (BpmnError e) {
441 } catch (Exception e) {
442 logger.error("{} {} {} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError.getValue(), "Exception is:\n" + e);
443 execution.setVariable("errorCode", "1002")
444 execution.setVariable("errorText", e.getMessage())
452 * Call APP-C client to execute specified APP-C command for this VNF.
455 * @param execution The flow's execution instance.
456 * @param action The action to take in APP-C.
458 public void runAppcCommand(DelegateExecution execution, Action action) {
459 def method = getClass().getSimpleName() + '.runAppcCommand(' +
460 'execution=' + execution.getId() +
463 execution.setVariable('errorCode', "0")
464 logger.trace('Entered ' + method)
466 ApplicationControllerClient appcClient = null
469 logger.debug("Running APP-C action: " + action.toString())
470 String vnfId = execution.getVariable('vnfId')
471 String msoRequestId = execution.getVariable('requestId')
472 execution.setVariable('msoRequestId', msoRequestId)
473 execution.setVariable("failedActivity", "APP-C")
475 appcClient = new ApplicationControllerClient()
476 ApplicationControllerSupport support = new ApplicationControllerSupport()
477 appcClient.appCSupport=support
478 org.springframework.test.util.ReflectionTestUtils.setField(support, "lcmModelPackage", "org.onap.appc.client.lcm.model");
479 Flags flags = new Flags();
480 ActionIdentifiers actionIdentifiers = new ActionIdentifiers();
481 actionIdentifiers.setVnfId(vnfId);
485 execution.setVariable('workStep', "LockVNF")
486 appcStatus = appcClient.runCommand(Action.Lock,actionIdentifiers,null,msoRequestId)
489 execution.setVariable('workStep', "UnlockVNF")
490 appcStatus = appcClient.runCommand(Action.Unlock,actionIdentifiers,null,msoRequestId)
492 case Action.HealthCheck:
493 def healthCheckIndex = execution.getVariable('healthCheckIndex')
494 execution.setVariable('workStep', "HealthCheckVNF" + healthCheckIndex)
495 execution.setVariable('healthCheckIndex', healthCheckIndex + 1)
496 appcStatus = appcClient.runCommand(Action.HealthCheck,actionIdentifiers,null,msoRequestId)
499 execution.setVariable('workStep', "StartVNF")
500 appcStatus = appcClient.runCommand(Action.Start,actionIdentifiers,null,msoRequestId)
503 execution.setVariable('workStep', "StopVNF")
504 appcStatus = appcClient.runCommand(Action.Stop,actionIdentifiers,null,msoRequestId)
509 logger.debug("Completed AppC request")
510 int appcCode = appcStatus.getCode()
511 logger.debug("AppC status code is: " + appcCode)
512 logger.debug("AppC status message is: " + appcStatus.getMessage())
513 if (support.getCategoryOf(appcStatus) == ApplicationControllerSupport.StatusCategory.ERROR) {
514 execution.setVariable("errorCode", Integer.toString(appcCode))
515 execution.setVariable("errorText", appcStatus.getMessage())
518 logger.trace('Exited ' + method)
519 } catch (BpmnError e) {
520 logger.error("{} {} {} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError.getValue(), "Exception is:\n" + e);
521 execution.setVariable("errorCode", "1002")
522 execution.setVariable("errorText", e.getMessage())
523 } catch (java.lang.NoSuchMethodError e) {
524 logger.error("{} {} {} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError.getValue(), "Exception is:\n" + e);
525 execution.setVariable("errorCode", "1002")
526 execution.setVariable("errorText", e.getMessage())
527 } catch (Exception e) {
528 logger.error("{} {} {} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError.getValue(), "Exception is:\n" + e);
529 execution.setVariable("errorCode", "1002")
530 execution.setVariable("errorText", e.getMessage())
535 * Placeholder for a call to APP-C client to execute specified APP-C command for this VNF.
538 * @param execution The flow's execution instance.
539 * @param action The action to take in APP-C.
541 public void runAppcCommandPlaceholder(DelegateExecution execution, String action) {
542 def method = getClass().getSimpleName() + '.runAppcCommandPlaceholder(' +
543 'execution=' + execution.getId() +
546 execution.setVariable('errorCode', "0")
547 logger.trace('Entered ' + method)
548 execution.setVariable("failedActivity", "APP-C")
549 execution.setVariable("workStep", action)
555 * Handle Abort disposition from RainyDayHandler
557 * @param execution The flow's execution instance.
559 public void abortProcessing(DelegateExecution execution) {
560 def method = getClass().getSimpleName() + '.abortProcessing(' +
561 'execution=' + execution.getId() +
564 logger.trace('Entered ' + method)
566 def errorText = execution.getVariable("errorText")
567 def errorCode = execution.getVariable("errorCode")
569 exceptionUtil.buildAndThrowWorkflowException(execution, errorCode as Integer, errorText)
573 * Increment Retry Count for Current Work Step
575 * @param execution The flow's execution instance.
577 public void incrementRetryCount(DelegateExecution execution) {
578 def method = getClass().getSimpleName() + '.incrementRetryCount(' +
579 'execution=' + execution.getId() +
582 logger.trace('Entered ' + method)
584 String retryCountVariableName = execution.getVariable("workStep") + "RetryCount"
585 execution.setVariable("retryCountVariableName", retryCountVariableName)
587 def retryCountVariable = execution.getVariable(retryCountVariableName)
590 if (retryCountVariable != null) {
591 retryCount = (int) retryCountVariable
596 execution.setVariable(retryCountVariableName, retryCount)
598 logger.debug("value of " + retryCountVariableName + " is " + retryCount)
599 logger.trace('Exited ' + method)