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.springframework.web.util.UriUtils
29 import org.onap.so.logger.MessageEnum
30 import org.onap.so.logger.MsoLogger
35 public class UpdateAAIVfModule extends AbstractServiceTaskProcessor {
36 private static final MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL, UpdateAAIVfModule.class);
39 private XmlParser xmlParser = new XmlParser()
40 ExceptionUtil exceptionUtil = new ExceptionUtil()
43 * Initialize the flow's variables.
45 * @param execution The flow's execution instance.
47 public void initProcessVariables(DelegateExecution execution) {
48 execution.setVariable('prefix', 'UAAIVfMod_')
49 execution.setVariable('UAAIVfMod_vnfId', null)
50 execution.setVariable('UAAIVfMod_vfModuleId', null)
51 execution.setVariable('UAAIVfMod_orchestrationStatus', null)
52 execution.setVariable('UAAIVfMod_heatStackId', null)
53 execution.setVariable('UAAIVfMod_volumeGroupId', null)
54 execution.setVariable('UAAIVfMod_getVfModuleResponseCode' ,null)
55 execution.setVariable('UAAIVfMod_getVfModuleResponse', '')
56 execution.setVariable('UAAIVfMod_updateVfModuleResponseCode', null)
57 execution.setVariable('UAAIVfMod_updateVfModuleResponse', '')
61 * Check for missing elements in the received request.
63 * @param execution The flow's execution instance.
65 public void preProcessRequest(DelegateExecution execution) {
66 def method = getClass().getSimpleName() + '.preProcessRequest(' +
67 'execution=' + execution.getId() +
69 msoLogger.trace('Entered ' + method)
72 def xml = execution.getVariable('UpdateAAIVfModuleRequest')
73 msoLogger.debug('Received request xml:\n' + xml)
74 initProcessVariables(execution)
76 def vnfId = getRequiredNodeText(execution, xml,'vnf-id')
77 execution.setVariable('UAAIVfMod_vnfId', vnfId)
79 def vfModuleId = getRequiredNodeText(execution, xml,'vf-module-id')
80 execution.setVariable('UAAIVfMod_vfModuleId', vfModuleId)
82 msoLogger.trace('Exited ' + method)
83 } catch (BpmnError e) {
85 } catch (Exception e) {
87 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in preProcessRequest(): ' + e.getMessage())
92 * Using the received vnfId and vfModuleId, query AAI to get the corresponding VF Module.
93 * A 200 response is expected with the VF Module in the response body.
95 * @param execution The flow's execution instance.
97 public void getVfModule(DelegateExecution execution) {
98 def method = getClass().getSimpleName() + '.getVfModule(' +
99 'execution=' + execution.getId() +
101 msoLogger.trace('Entered ' + method)
104 def vnfId = execution.getVariable('UAAIVfMod_vnfId')
105 def vfModuleId = execution.getVariable('UAAIVfMod_vfModuleId')
107 // Construct endpoint
108 AaiUtil aaiUriUtil = new AaiUtil(this)
109 def aai_uri = aaiUriUtil.getNetworkGenericVnfUri(execution)
110 msoLogger.debug('AAI URI is: ' + aai_uri)
111 String endPoint = UrnPropertiesReader.getVariable("aai.endpoint", execution) + aai_uri + '/' + UriUtils.encode(vnfId, "UTF-8") + '/vf-modules/vf-module/' + UriUtils.encode(vfModuleId, "UTF-8")
114 msoLogger.debug('sending GET to AAI endpoint \'' + endPoint + '\'')
115 msoLogger.debug("UpdateAAIVfModule sending GET to AAI endpoint: " + endPoint)
117 APIResponse response = aaiUriUtil.executeAAIGetCall(execution, endPoint)
118 def responseData = response.getResponseBodyAsString()
119 execution.setVariable('UAAIVfMod_getVfModuleResponseCode', response.getStatusCode())
120 execution.setVariable('UAAIVfMod_getVfModuleResponse', responseData)
121 msoLogger.debug('Response code:' + response.getStatusCode())
122 msoLogger.debug('Response:' + System.lineSeparator() + responseData)
123 msoLogger.debug("UpdateAAIVfModule response data: " + responseData)
124 } catch (Exception ex) {
126 msoLogger.debug('Exception occurred while executing AAI GET:' + ex.getMessage())
127 execution.setVariable('UAAIVfMod_getVfModuleResponseCode', 500)
128 execution.setVariable('UAAIVfMod_getVfModuleResponse', 'AAI GET Failed:' + ex.getMessage())
130 msoLogger.trace('Exited ' + method)
131 } catch (BpmnError e) {
133 } catch (Exception e) {
135 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in getVfModule(): ' + e.getMessage())
140 * Construct and send a PATCH request to AAI to update the VF Module.
142 * @param execution The flow's execution instance.
144 public void updateVfModule(DelegateExecution execution) {
145 def method = getClass().getSimpleName() + '.updateVfModule(' +
146 'execution=' + execution.getId() +
148 msoLogger.trace('Entered ' + method)
151 def vnfId = execution.getVariable('UAAIVfMod_vnfId')
152 def vfModuleId = execution.getVariable('UAAIVfMod_vfModuleId')
153 def vfModule = execution.getVariable('UAAIVfMod_getVfModuleResponse')
154 def origRequest = execution.getVariable('UpdateAAIVfModuleRequest')
155 def Node vfModuleNode = xmlParser.parseText(vfModule)
157 msoLogger.debug("UpdateAAIVfModule request: " + origRequest)
158 // Confirm resource-version is in retrieved VF Module
159 if (utils.getChildNode(vfModuleNode, 'resource-version') == null) {
160 def msg = 'Can\'t update VF Module ' + vfModuleId + ' since \'resource-version\' is missing'
161 msoLogger.error(msg);
162 throw new Exception(msg)
165 // Handle persona-model-id/persona-model-version
166 def boolean doPersonaModelVersion = true
167 def String newPersonaModelId = utils.getNodeText(origRequest, 'persona-model-id')
168 def String newPersonaModelVersion = utils.getNodeText(origRequest, 'persona-model-version')
169 if ((newPersonaModelId == null) || (newPersonaModelVersion == null)) {
170 doPersonaModelVersion = false
172 // Confirm "new" persona-model-id is same as "current" persona-model-id
173 def String currPersonaModelId = utils.getChildNodeText(vfModuleNode, 'model-invariant-id')
174 if (currPersonaModelId == null) {
175 // check the old attribute name
176 currPersonaModelId = utils.getChildNodeText(vfModuleNode, 'model-version-id')
178 if (currPersonaModelId == null) {
179 currPersonaModelId = ''
181 if (!newPersonaModelId.equals(currPersonaModelId)) {
182 def msg = 'Can\'t update VF Module ' + vfModuleId + ' since there is \'persona-model-id\' mismatch between the current and new values'
184 throw new Exception(msg)
189 String orchestrationStatusEntry = updateVfModuleNode(origRequest, vfModuleNode, 'orchestration-status')
190 String heatStackIdEntry = updateVfModuleNode(origRequest, vfModuleNode, 'heat-stack-id')
191 String personaModelVersionEntry = ""
192 if (doPersonaModelVersion) {
193 personaModelVersionEntry = updateVfModuleNode(origRequest, vfModuleNode, 'persona-model-version')
195 String contrailServiceInstanceFqdnEntry = updateVfModuleNode(origRequest, vfModuleNode, 'contrail-service-instance-fqdn')
197 { ${orchestrationStatusEntry}
199 ${personaModelVersionEntry}
200 ${contrailServiceInstanceFqdnEntry}
201 "vf-module-id": "${vfModuleId}"
206 // Construct endpoint
207 AaiUtil aaiUriUtil = new AaiUtil(this)
208 def aai_uri = aaiUriUtil.getNetworkGenericVnfUri(execution)
209 msoLogger.debug('AAI URI is: ' + aai_uri)
210 String endPoint = UrnPropertiesReader.getVariable("aai.endpoint", execution) + aai_uri + '/' + UriUtils.encode(vnfId, "UTF-8") + '/vf-modules/vf-module/' + UriUtils.encode(vfModuleId, "UTF-8")
213 msoLogger.debug('sending PATCH to AAI endpoint \'' + endPoint + '\'' + 'with payload \n' + payload)
214 msoLogger.debug("Sending PATCH to AAI endpoint: " + endPoint)
216 APIResponse response = aaiUriUtil.executeAAIPatchCall(execution, endPoint, payload)
217 def responseData = response.getResponseBodyAsString()
218 execution.setVariable('UAAIVfMod_updateVfModuleResponseCode', response.getStatusCode())
219 execution.setVariable('UAAIVfMod_updateVfModuleResponse', responseData)
220 msoLogger.debug("UpdateAAIVfModule Response data: " + responseData)
221 msoLogger.debug('Response code:' + response.getStatusCode())
222 msoLogger.debug('Response:' + System.lineSeparator() + responseData)
223 } catch (Exception ex) {
225 msoLogger.debug('Exception occurred while executing AAI PATCH:' + ex.getMessage())
226 execution.setVariable('UAAIVfMod_updateVfModuleResponseCode', 500)
227 execution.setVariable('UAAIVfMod_updateVfModuleResponse', 'AAI PATCH Failed:' + ex.getMessage())
229 msoLogger.trace('Exited ' + method)
230 } catch (BpmnError e) {
232 } catch (Exception e) {
234 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in updateVfModule(): ' + e.getMessage())
239 * Sets up json attributes for PATCH request for Update
241 * @param origRequest Incoming update request with VF Module elements to be updated.
242 * @param vfModule Current VF Module retrieved from AAI.
243 * @param element Name of element to be inserted.
245 private String updateVfModuleNode(String origRequest, Node vfModuleNode, String elementName) {
247 if (!utils.nodeExists(origRequest, elementName)) {
250 def elementValue = utils.getNodeText(origRequest, elementName)
252 if (elementValue.equals('DELETE')) {
253 // Set the element being deleted to null
254 return """"${elementName}": null,"""
257 return """"${elementName}": "${elementValue}","""
263 * Check the Volume Group ID from the incoming update request against the Volume Group ID from the
264 * given VF Module. If they are equal or if they are both 'null', then that is acceptable and 'null'
265 * is returned. Otherwise a message describing how the values are unacceptable/incompatible is returned.
267 * @param origRequest Incoming update request with VF Module elements to be updated.
268 * @param vfModuleNode VF Module (as a Node) retrieved from AAI.
269 * @param isDebugLogEnabled Is DEBUG log enabled?
270 * @return 'null' if the Volume Group IDs are acceptable. Otherwise return a message describing how the
271 * values are unacceptable/incompatible.
273 private String checkVolumeGroupId(String origRequest, Node vfModuleNode, String isDebugLogEnabled) {
274 def requestVolumeGroupId = utils.getNodeText(origRequest, 'volume-group-id')
275 def currVolumeGroupId = getCurrVolumeGroupId(vfModuleNode)
277 msoLogger.debug('Check volume-group-id: volume-group-id in original request is \'' + requestVolumeGroupId + '\', volume-group-id from VF Module is \'' + currVolumeGroupId + '\'')
281 if (requestVolumeGroupId == null) {
282 if (currVolumeGroupId == null) {
285 result = 'Cannot detach a volume group from an existing VF Module'
288 if (currVolumeGroupId == null) {
289 result = 'Cannot add a volume gruop to an existing VF Module'
291 if (!requestVolumeGroupId.equals(currVolumeGroupId)) {
292 result = 'Cannot change the volume group on an existing VF Module'
301 * Find and return the value of the Volume Group ID for the specified VF Module. If
302 * the value of the Volume Group ID cannot be found for any reason, 'null' is returned.
304 * @param vfModuleNode VF Module (as a Node) retrieved from AAI.
305 * @return the value of the Volume Group ID for the specified VF Module. If the
306 * value of the Volume Group ID cannot be found for any reason, 'null' is returned.
308 private String getCurrVolumeGroupId(Node vfModuleNode) {
309 def Node relationshipList = utils.getChildNode(vfModuleNode, 'relationship-list')
310 if (relationshipList == null) {
313 def NodeList relationships = utils.getIdenticalChildren(relationshipList, 'relationship')
314 for (Node relationshipNode in relationships) {
315 def String relatedTo = utils.getChildNodeText(relationshipNode, 'related-to')
316 if ((relatedTo != null) && relatedTo.equals('volume-group')) {
317 def NodeList relationshipDataList = utils.getIdenticalChildren(relationshipNode, 'relationship-data')
318 for (Node relationshipDataNode in relationshipDataList) {
319 def String relationshipKey = utils.getChildNodeText(relationshipDataNode, 'relationship-key')
320 if ((relationshipKey != null) && relationshipKey.equals('volume-group.volume-group-id')) {
321 return utils.getChildNodeText(relationshipDataNode, 'relationship-value')
330 * Generates a WorkflowException if the AAI query returns a response code other than 200.
332 * @param execution The flow's execution instance.
334 public void handleAAIQueryFailure(DelegateExecution execution) {
335 def method = getClass().getSimpleName() + '.handleAAIQueryFailure(' +
336 'execution=' + execution.getId() +
338 msoLogger.trace('Entered ' + method)
340 msoLogger.error( 'Error occurred attempting to query AAI, Response Code ' + execution.getVariable('UAAIVfMod_getVfModuleResponseCode'));
341 String processKey = getProcessKey(execution);
342 WorkflowException exception = new WorkflowException(processKey, 5000,
343 execution.getVariable('UAAIVfMod_getVfModuleResponse'))
344 execution.setVariable('WorkflowException', exception)
345 msoLogger.debug("UpdateAAIVfModule query failure: " + exception.getErrorMessage())
346 msoLogger.trace('Exited ' + method)
350 * Generates a WorkflowException if updating a VF Module in AAI returns a response code other than 200.
352 * @param execution The flow's execution instance.
354 public void handleUpdateVfModuleFailure(DelegateExecution execution) {
355 def method = getClass().getSimpleName() + '.handleUpdateVfModuleFailure(' +
356 'execution=' + execution.getId() +
358 msoLogger.trace('Entered ' + method)
360 msoLogger.error('Error occurred attempting to update VF Module in AAI, Response Code ' + execution.getVariable('UAAIVfMod_updateVfModuleResponseCode'));
361 String processKey = getProcessKey(execution);
362 WorkflowException exception = new WorkflowException(processKey, 5000,
363 execution.getVariable('UAAIVfMod_updateVfModuleResponse'))
364 execution.setVariable('WorkflowException', exception)
366 msoLogger.debug("UpdateAAIVfModule failure: " + exception.getErrorMessage())
367 msoLogger.trace('Exited ' + method)