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.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.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.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.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' +
355 ' ' + method, "BPMN", MsoLogger.ErrorCode.UnknownError.getValue(), "Exception is:\n" + e);
356 execution.setVariable("errorCode", "1002")
357 execution.setVariable("errorText", e.getMessage())
362 * Check if VF Closed Loop Disabled in A&AI.
365 * @param execution The flow's execution instance.
367 public void checkIfClosedLoopDisabledInAAI(DelegateExecution execution) {
368 def method = getClass().getSimpleName() + '.checkIfClosedLoopDisabledInAAI(' +
369 'execution=' + execution.getId() +
372 execution.setVariable('errorCode', "0")
373 execution.setVariable("workStep", "checkClosedLoopDisabledFlagInAAI")
374 execution.setVariable("failedActivity", "AAI")
375 logger.trace('Entered ' + method)
378 def transactionLoggingUuid = UUID.randomUUID().toString()
379 def vnfId = execution.getVariable("vnfId")
380 logger.debug("vnfId is: " + vnfId)
381 AAIResourcesClient client = new AAIResourcesClient()
382 AAIUri genericVnfUri = AAIUriFactory.createResourceUri(AAIObjectType.GENERIC_VNF, vnfId)
383 AAIResultWrapper aaiRW = client.get(genericVnfUri)
384 Map<String, Object> result = aaiRW.asMap()
385 boolean isClosedLoopDisabled = result.getOrDefault("is-closed-loop-disabled", false)
387 logger.debug("isClosedLoopDisabled result: " + isClosedLoopDisabled)
388 execution.setVariable('isClosedLoopDisabled', isClosedLoopDisabled)
390 if (isClosedLoopDisabled) {
391 execution.setVariable("errorCode", "1004")
392 execution.setVariable("errorText", "closedLoop is disabled in A&AI")
395 logger.trace('Exited ' + method)
396 } catch (BpmnError e) {
398 } catch (Exception e) {
399 logger.error("{} {} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), 'Caught exception in' +
400 ' ' + method, "BPMN", MsoLogger.ErrorCode.UnknownError.getValue(), "Exception is:\n" + e);
401 execution.setVariable("errorCode", "1002")
402 execution.setVariable("errorText", e.getMessage())
407 * Set VF Closed Loop Disabled Flag in A&AI.
410 * @param execution The flow's execution instance.
412 public void setClosedLoopDisabledInAAI(DelegateExecution execution, boolean setDisabled) {
413 def method = getClass().getSimpleName() + '.setClosedLoopDisabledInAAI(' +
414 'execution=' + execution.getId() +
417 execution.setVariable('errorCode', "0")
419 execution.setVariable("workStep", "setClosedLoopDisabledFlagInAAI")
420 execution.setVariable("rollbackSetClosedLoopDisabledFlag", true)
423 execution.setVariable("workStep", "unsetClosedLoopDisabledFlagInAAI")
426 execution.setVariable("failedActivity", "AAI")
427 logger.trace('Entered ' + method)
430 def transactionLoggingUuid = UUID.randomUUID().toString()
431 def vnfId = execution.getVariable("vnfId")
432 AAIResourcesClient client = new AAIResourcesClient()
433 AAIUri genericVnfUri = AAIUriFactory.createResourceUri(AAIObjectType.GENERIC_VNF, vnfId)
435 Map<String, Boolean> request = new HashMap<>()
436 request.put("is-closed-loop-disabled", setDisabled)
437 client.update(genericVnfUri, request)
438 logger.debug("set isClosedLoop to: " + setDisabled)
440 logger.trace('Exited ' + method)
441 } catch (BpmnError e) {
443 } catch (Exception e) {
444 logger.error("{} {} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), 'Caught exception in' +
445 ' ' + method, "BPMN", MsoLogger.ErrorCode.UnknownError.getValue(), "Exception is:\n" + e);
446 execution.setVariable("errorCode", "1002")
447 execution.setVariable("errorText", e.getMessage())
455 * Call APP-C client to execute specified APP-C command for this VNF.
458 * @param execution The flow's execution instance.
459 * @param action The action to take in APP-C.
461 public void runAppcCommand(DelegateExecution execution, Action action) {
462 def method = getClass().getSimpleName() + '.runAppcCommand(' +
463 'execution=' + execution.getId() +
466 execution.setVariable('errorCode', "0")
467 logger.trace('Entered ' + method)
469 ApplicationControllerClient appcClient = null
472 logger.debug("Running APP-C action: " + action.toString())
473 String vnfId = execution.getVariable('vnfId')
474 String msoRequestId = execution.getVariable('requestId')
475 execution.setVariable('msoRequestId', msoRequestId)
476 execution.setVariable("failedActivity", "APP-C")
478 appcClient = new ApplicationControllerClient()
479 ApplicationControllerSupport support = new ApplicationControllerSupport()
480 appcClient.appCSupport=support
481 org.springframework.test.util.ReflectionTestUtils.setField(support, "lcmModelPackage", "org.onap.appc.client.lcm.model");
482 Flags flags = new Flags();
483 ActionIdentifiers actionIdentifiers = new ActionIdentifiers();
484 actionIdentifiers.setVnfId(vnfId);
488 execution.setVariable('workStep', "LockVNF")
489 appcStatus = appcClient.runCommand(Action.Lock,actionIdentifiers,null,msoRequestId)
492 execution.setVariable('workStep', "UnlockVNF")
493 appcStatus = appcClient.runCommand(Action.Unlock,actionIdentifiers,null,msoRequestId)
495 case Action.HealthCheck:
496 def healthCheckIndex = execution.getVariable('healthCheckIndex')
497 execution.setVariable('workStep', "HealthCheckVNF" + healthCheckIndex)
498 execution.setVariable('healthCheckIndex', healthCheckIndex + 1)
499 appcStatus = appcClient.runCommand(Action.HealthCheck,actionIdentifiers,null,msoRequestId)
502 execution.setVariable('workStep', "StartVNF")
503 appcStatus = appcClient.runCommand(Action.Start,actionIdentifiers,null,msoRequestId)
506 execution.setVariable('workStep', "StopVNF")
507 appcStatus = appcClient.runCommand(Action.Stop,actionIdentifiers,null,msoRequestId)
512 logger.debug("Completed AppC request")
513 int appcCode = appcStatus.getCode()
514 logger.debug("AppC status code is: " + appcCode)
515 logger.debug("AppC status message is: " + appcStatus.getMessage())
516 if (support.getCategoryOf(appcStatus) == ApplicationControllerSupport.StatusCategory.ERROR) {
517 execution.setVariable("errorCode", Integer.toString(appcCode))
518 execution.setVariable("errorText", appcStatus.getMessage())
521 logger.trace('Exited ' + method)
522 } catch (BpmnError e) {
523 logger.error("{} {} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), 'Caught exception in' +
524 ' ' + method, "BPMN", MsoLogger.ErrorCode.UnknownError.getValue(), "Exception is:\n" + e);
525 execution.setVariable("errorCode", "1002")
526 execution.setVariable("errorText", e.getMessage())
527 } catch (java.lang.NoSuchMethodError e) {
528 logger.error("{} {} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), 'Caught exception in' +
529 ' ' + method, "BPMN", MsoLogger.ErrorCode.UnknownError.getValue(), "Exception is:\n" + e);
530 execution.setVariable("errorCode", "1002")
531 execution.setVariable("errorText", e.getMessage())
532 } catch (Exception e) {
533 logger.error("{} {} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), 'Caught exception in' +
534 ' ' + method, "BPMN", MsoLogger.ErrorCode.UnknownError.getValue(), "Exception is:\n" + e);
535 execution.setVariable("errorCode", "1002")
536 execution.setVariable("errorText", e.getMessage())
541 * Placeholder for a call to APP-C client to execute specified APP-C command for this VNF.
544 * @param execution The flow's execution instance.
545 * @param action The action to take in APP-C.
547 public void runAppcCommandPlaceholder(DelegateExecution execution, String action) {
548 def method = getClass().getSimpleName() + '.runAppcCommandPlaceholder(' +
549 'execution=' + execution.getId() +
552 execution.setVariable('errorCode', "0")
553 logger.trace('Entered ' + method)
554 execution.setVariable("failedActivity", "APP-C")
555 execution.setVariable("workStep", action)
561 * Handle Abort disposition from RainyDayHandler
563 * @param execution The flow's execution instance.
565 public void abortProcessing(DelegateExecution execution) {
566 def method = getClass().getSimpleName() + '.abortProcessing(' +
567 'execution=' + execution.getId() +
570 logger.trace('Entered ' + method)
572 def errorText = execution.getVariable("errorText")
573 def errorCode = execution.getVariable("errorCode")
575 exceptionUtil.buildAndThrowWorkflowException(execution, errorCode as Integer, errorText)
579 * Increment Retry Count for Current Work Step
581 * @param execution The flow's execution instance.
583 public void incrementRetryCount(DelegateExecution execution) {
584 def method = getClass().getSimpleName() + '.incrementRetryCount(' +
585 'execution=' + execution.getId() +
588 logger.trace('Entered ' + method)
590 String retryCountVariableName = execution.getVariable("workStep") + "RetryCount"
591 execution.setVariable("retryCountVariableName", retryCountVariableName)
593 def retryCountVariable = execution.getVariable(retryCountVariableName)
596 if (retryCountVariable != null) {
597 retryCount = (int) retryCountVariable
602 execution.setVariable(retryCountVariableName, retryCount)
604 logger.debug("value of " + retryCountVariableName + " is " + retryCount)
605 logger.trace('Exited ' + method)