2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.onap.so.bpmn.common.scripts
23 import org.camunda.bpm.engine.delegate.BpmnError
24 import org.camunda.bpm.engine.delegate.DelegateExecution
25 import org.onap.so.bpmn.core.WorkflowException
26 import org.onap.so.bpmn.core.UrnPropertiesReader
27 import org.onap.so.rest.APIResponse
28 import org.onap.so.rest.RESTClient
29 import org.onap.so.rest.RESTConfig
30 import org.springframework.web.util.UriUtils
31 import org.onap.so.logger.MessageEnum
32 import org.onap.so.logger.MsoLogger
36 public class PrepareUpdateAAIVfModule extends VfModuleBase {
37 private static final MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL, PrepareUpdateAAIVfModule.class);
40 ExceptionUtil exceptionUtil = new ExceptionUtil()
41 private MsoUtils utils = new MsoUtils()
43 * Initialize the flow's variables.
45 * @param execution The flow's execution instance.
47 public void initProcessVariables(DelegateExecution execution) {
48 execution.setVariable('prefix', 'PUAAIVfMod_')
49 execution.setVariable('PUAAIVfMod_vnfId', null)
50 execution.setVariable('PUAAIVfMod_vfModuleId', null)
51 execution.setVariable('PUAAIVfMod_vnfName', null)
52 execution.setVariable('PUAAIVfMod_orchestrationStatus', null)
53 execution.setVariable('PUAAIVfMod_vfModule', null)
54 execution.setVariable('PUAAIVfMod_vfModuleOK', false)
55 execution.setVariable('PUAAIVfMod_vfModuleValidationError', null)
56 execution.setVariable('PUAAIVfMod_getVnfResponseCode' ,null)
57 execution.setVariable('PUAAIVfMod_getVnfResponse', '')
58 execution.setVariable('PUAAIVfMod_updateVfModuleResponseCode', null)
59 execution.setVariable('PUAAIVfMod_updateVfModuleResponse', '')
60 execution.setVariable('PUAAIVfMod_outVfModule', null)
64 * Check for missing elements in the received request.
66 * @param execution The flow's execution instance.
68 public void preProcessRequest(DelegateExecution execution) {
69 def method = getClass().getSimpleName() + '.preProcessRequest(' +
70 'execution=' + execution.getId() +
72 msoLogger.trace('Entered ' + method)
75 def xml = execution.getVariable('PrepareUpdateAAIVfModuleRequest')
76 msoLogger.debug('Received request xml:\n' + xml)
77 msoLogger.debug("PrepareUpdateAAIVfModule Request : " + xml)
79 initProcessVariables(execution)
81 def vnfId = getRequiredNodeText(execution, xml,'vnf-id')
82 execution.setVariable('PUAAIVfMod_vnfId', vnfId)
84 def vfModuleId = getRequiredNodeText(execution, xml,'vf-module-id')
85 execution.setVariable('PUAAIVfMod_vfModuleId', vfModuleId)
87 def orchestrationStatus = getRequiredNodeText(execution, xml,'orchestration-status')
88 execution.setVariable('PUAAIVfMod_orchestrationStatus', orchestrationStatus)
90 msoLogger.trace('Exited ' + method)
91 } catch (BpmnError e) {
93 } catch (Exception e) {
95 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in preProcessRequest(): ' + e.getMessage())
100 * Using the received vnfId, query AAI to get the corresponding Generic VNF.
101 * A 200 response is expected with the Generic VNF in the response body.
103 * @param execution The flow's execution instance.
105 public void getGenericVnf(DelegateExecution execution) {
106 def method = getClass().getSimpleName() + '.getGenericVnf(' +
107 'execution=' + execution.getId() +
109 msoLogger.trace('Entered ' + method)
112 def vnfId = execution.getVariable('PUAAIVfMod_vnfId')
114 AaiUtil aaiUriUtil = new AaiUtil(this)
115 def aai_uri = aaiUriUtil.getNetworkGenericVnfUri(execution)
116 msoLogger.debug('AAI URI is: ' + aai_uri)
118 String endPoint = UrnPropertiesReader.getVariable("aai.endpoint", execution) + "${aai_uri}/" + UriUtils.encode(vnfId, "UTF-8") + "?depth=1"
120 msoLogger.debug("PrepareUpdateAAIVfModule: AAI endPoint : " + endPoint)
121 String basicAuthCred = utils.getBasicAuth(UrnPropertiesReader.getVariable("aai.auth", execution),UrnPropertiesReader.getVariable("mso.msoKey", execution))
123 RESTConfig config = new RESTConfig(endPoint);
124 def responseData = ''
125 String aaiRequestId = utils.getRequestID()
126 RESTClient client = new RESTClient(config).
127 addHeader('X-TransactionId', aaiRequestId).
128 addHeader('X-FromAppId', 'MSO').
129 addHeader('Content-Type', 'application/xml').
130 addHeader('Accept','application/xml');
131 if (basicAuthCred != null && !"".equals(basicAuthCred)) {
132 client.addAuthorizationHeader(basicAuthCred)
134 msoLogger.debug('sending GET to AAI endpoint \'' + endPoint + '\'')
135 APIResponse response = client.httpGet()
136 msoLogger.debug("PrepareUpdateAAIVfModule: - invoking httpGet to AAI")
138 responseData = response.getResponseBodyAsString()
139 execution.setVariable('PUAAIVfMod_getVnfResponseCode', response.getStatusCode())
140 execution.setVariable('PUAAIVfMod_getVnfResponse', responseData)
142 msoLogger.debug("PrepareUpdateAAIVfModule: AAI Response : " + responseData)
143 msoLogger.debug("PrepareUpdateAAIVfModule: AAI ResponseCode : " + response.getStatusCode())
145 msoLogger.debug('Response code:' + response.getStatusCode())
146 msoLogger.debug('Response:' + System.lineSeparator() + responseData)
147 } catch (Exception ex) {
149 msoLogger.debug('Exception occurred while executing AAI GET:' + ex.getMessage())
150 execution.setVariable('PUAAIVfMod_getVnfResponseCode', 500)
151 execution.setVariable('PUAAIVfMod_getVnfResponse', 'AAI GET Failed:' + ex.getMessage())
153 msoLogger.trace('Exited ' + method)
154 } catch (BpmnError e) {
156 } catch (Exception e) {
158 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in getGenericVnf(): ' + e.getMessage())
163 * Validate the VF Module. That is, confirm that a VF Module with the input VF Module ID
164 * exists in the retrieved Generic VNF. Then, check to make sure that if that VF Module
165 * is the base VF Module and it's not the only VF Module for this Generic VNF, that we're not
166 * attempting to delete it.
168 * @param execution The flow's execution instance.
170 public void validateVfModule(DelegateExecution execution) {
171 def method = getClass().getSimpleName() + '.validateVfModule(' +
172 'execution=' + execution.getId() +
174 msoLogger.trace('Entered ' + method)
177 def genericVnf = execution.getVariable('PUAAIVfMod_getVnfResponse')
178 def vnfId = execution.getVariable('PUAAIVfMod_vnfId')
179 def vfModuleId = execution.getVariable('PUAAIVfMod_vfModuleId')
180 def vnfName = getNodeTextForce(genericVnf, 'vnf-name')
181 execution.setVariable('PUAAIVfMod_vnfName', vnfName)
182 def VfModule vfModule = findVfModule(genericVnf, vfModuleId)
183 if (vfModule == null) {
184 def String msg = 'VF Module \'' + vfModuleId + '\' does not exist in Generic VNF \'' + vnfId + '\''
185 execution.setVariable('PUAAIVfMod_vfModuleValidationError', msg)
186 execution.setVariable('PUAAIVfMod_vfModuleOK', false)
188 def orchestrationStatus = execution.getVariable('PUAAIVfMod_orchestrationStatus')
189 msoLogger.debug('VF Module \'' + vfModuleId + '\': isBaseVfModule=' + vfModule.isBaseVfModule() +', isOnlyVfModule=' + vfModule.isOnlyVfModule() + ', new orchestration-status=' + orchestrationStatus)
190 if (vfModule.isBaseVfModule() && !vfModule.isOnlyVfModule() && orchestrationStatus.equals('pending-delete')) {
191 def String msg = 'Orchestration status for VF Module \'' + vfModuleId +
192 '\' cannot be set to \'pending-delete\' since it is the base VF Module and it\'s not the only VF Module in Generic VNF \'' + vnfId + '\''
193 execution.setVariable('PUAAIVfMod_vfModuleValidationError', msg)
194 execution.setVariable('PUAAIVfMod_vfModuleOK', false)
196 execution.setVariable('PUAAIVfMod_vfModule', vfModule)
197 execution.setVariable('PUAAIVfMod_vfModuleOK', true)
201 msoLogger.trace('Exited ' + method)
202 } catch (BpmnError e) {
204 } catch (Exception e) {
206 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in validateVfModule(): ' + e.getMessage())
211 * Construct and send a PATCH request to AAI to update the VF Module.
213 * @param execution The flow's execution instance.
215 public void updateVfModule(DelegateExecution execution) {
216 def method = getClass().getSimpleName() + '.updateVfModule(' +
217 'execution=' + execution.getId() +
219 msoLogger.trace('Entered ' + method)
223 def VfModule vfModule = (VfModule) execution.getVariable('PUAAIVfMod_vfModule')
224 def Node newVfModuleNode = vfModule.getNode().clone()
225 def orchestrationStatus = execution.getVariable('PUAAIVfMod_orchestrationStatus')
226 def Node orchestrationStatusNode = utils.getChildNode(newVfModuleNode, 'orchestration-status')
227 if (orchestrationStatusNode == null) {
228 // Node doesn't exist, this should never happen, right?
229 new Node(newVfModuleNode, 'orchestration-status', orchestrationStatus)
231 // Node already exists, just give it a new value
232 orchestrationStatusNode.setValue(orchestrationStatus)
234 def VfModule newVfModule = new VfModule(newVfModuleNode, vfModule.isOnlyVfModule())
235 //def payload = utils.nodeToString(newVfModuleNode)
237 // Construct endpoint
238 def vnfId = execution.getVariable('PUAAIVfMod_vnfId')
239 def vfModuleId = execution.getVariable('PUAAIVfMod_vfModuleId')
242 "vf-module-id": "${vfModuleId}",
243 "orchestration-status": "${orchestrationStatus}"
246 msoLogger.debug("VfModule payload : " + payload)
248 AaiUtil aaiUriUtil = new AaiUtil(this)
249 def aai_uri = aaiUriUtil.getNetworkGenericVnfUri(execution)
250 msoLogger.debug('AAI URI is: ' + aai_uri)
252 String endPoint = UrnPropertiesReader.getVariable("aai.endpoint", execution) + "${aai_uri}/" + UriUtils.encode(vnfId, "UTF-8") + "/vf-modules/vf-module/" + UriUtils.encode(vfModuleId, "UTF-8")
253 msoLogger.debug("PrepareUpdateAAIVfModule: AAI endPoint : " + endPoint)
254 String basicAuthCred = utils.getBasicAuth(UrnPropertiesReader.getVariable("aai.auth", execution),UrnPropertiesReader.getVariable("mso.msoKey", execution))
256 RESTConfig config = new RESTConfig(endPoint);
257 def responseData = ''
258 def aaiRequestId = utils.getRequestID()
259 RESTClient client = new RESTClient(config).
260 addHeader('X-TransactionId', aaiRequestId).
261 addHeader('X-FromAppId', 'MSO').
262 addHeader('Content-Type', 'application/merge-patch+json').
263 addHeader('Accept','application/json');
264 if (basicAuthCred != null && !"".equals(basicAuthCred)) {
265 client.addAuthorizationHeader(basicAuthCred)
267 msoLogger.debug('sending PATCH to AAI endpoint \'' + endPoint + '\'' + 'with payload \n' + payload)
268 APIResponse response = client.httpPatch(payload)
269 msoLogger.debug("PrepareUpdateAAIVfModule: - invoking httpPatch to AAI")
271 responseData = response.getResponseBodyAsString()
272 execution.setVariable('PUAAIVfMod_updateVfModuleResponseCode', response.getStatusCode())
273 execution.setVariable('PUAAIVfMod_updateVfModuleResponse', responseData)
274 msoLogger.debug('Response code:' + response.getStatusCode())
275 msoLogger.debug('Response:' + System.lineSeparator() + responseData)
276 msoLogger.debug("PrepareUpdateAAIVfModule: AAI Response : " + responseData)
277 msoLogger.debug("PrepareUpdateAAIVfModule: AAI ResponseCode : " + response.getStatusCode())
279 // Set the output for this flow. The updated VfModule is an output, the generic VNF name, and for
280 // backward compatibilty, the heat-stack-id is an output
281 execution.setVariable('PUAAIVfMod_outVfModule', newVfModule)
282 def vnfName = execution.getVariable('PUAAIVfMod_vnfName')
283 msoLogger.debug('Output PUAAIVfMod_vnfName set to ' + vnfName)
284 // TODO: Should deprecate use of processKey+Response variable for the response. Will use "WorkflowResponse" instead
285 execution.setVariable('WorkflowResponse', newVfModule)
286 msoLogger.debug('Output PUAAIVfMod_outVfModule set for VF Module Id \'' + newVfModule.getElementText('vf-module-id') + '\'')
287 def heatStackId = newVfModule.getElementText('heat-stack-id')
288 execution.setVariable('PUAAIVfMod_heatStackId', heatStackId)
289 msoLogger.debug('Output PUAAIVfMod_heatStackId set to \'' + heatStackId + '\'')
290 } catch (Exception ex) {
292 msoLogger.debug('Exception occurred while executing AAI PUT:' + ex.getMessage())
293 execution.setVariable('PUAAIVfMod_updateVfModuleResponseCode', 500)
294 execution.setVariable('PUAAIVfMod_updateVfModuleResponse', 'AAI PATCH Failed:' + ex.getMessage())
296 msoLogger.trace('Exited ' + method)
297 } catch (BpmnError e) {
299 } catch (Exception e) {
301 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in updateVfModule(): ' + e.getMessage())
306 * Generates a WorkflowException if the AAI query returns a response code other than 200.
308 * @param execution The flow's execution instance.
310 public void handleVnfNotFound(DelegateExecution execution) {
311 def method = getClass().getSimpleName() + '.handleVnfNotFound(' +
312 'execution=' + execution.getId() +
314 msoLogger.trace('Entered ' + method)
316 msoLogger.error('Error occurred attempting to query AAI, Response Code ' + execution.getVariable('PUAAIVfMod_getVnfResponseCode'));
317 String processKey = getProcessKey(execution);
318 WorkflowException exception = new WorkflowException(processKey, 5000,
319 execution.getVariable('PUAAIVfMod_getVnfResponse'))
320 execution.setVariable('WorkflowException', exception)
322 msoLogger.trace('Exited ' + method)
326 * Generates a WorkflowException if the VF Module does not pass validation.
328 * @param execution The flow's execution instance.
330 public void handleVfModuleValidationError(DelegateExecution execution) {
331 def method = getClass().getSimpleName() + '.handleVfModuleValidationError(' +
332 'execution=' + execution.getId() +
334 msoLogger.trace('Entered ' + method)
336 def String errorMsg = 'VF Module validation error: ' + execution.getVariable('PUAAIVfMod_vfModuleValidationError')
337 msoLogger.error(errorMsg);
338 msoLogger.debug("PrepareUpdateAAIVfModule: Error Message : " + errorMsg)
340 String processKey = getProcessKey(execution);
341 WorkflowException exception = new WorkflowException(processKey, 5000, errorMsg)
342 execution.setVariable('WorkflowException', exception)
344 msoLogger.trace('Exited ' + method)
348 * Generates a WorkflowException if updating a VF Module in AAI returns a response code other than 200.
350 * @param execution The flow's execution instance.
352 public void handleUpdateVfModuleFailure(DelegateExecution execution) {
353 def method = getClass().getSimpleName() + '.handleUpdateVfModuleFailure(' +
354 'execution=' + execution.getId() +
356 msoLogger.trace('Entered ' + method)
358 msoLogger.error('Error occurred attempting to update VF Module in AAI, Response Code ' + execution.getVariable('PUAAIVfMod_updateVfModuleResponseCode'));
359 String processKey = getProcessKey(execution);
360 WorkflowException exception = new WorkflowException(processKey, 5000,
361 execution.getVariable('PUAAIVfMod_updateVfModuleResponse'))
362 execution.setVariable('WorkflowException', exception)
364 msoLogger.trace('Exited ' + method)