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.client.aai.AAIObjectType
28 import org.onap.so.client.aai.entities.uri.AAIResourceUri
29 import org.onap.so.client.aai.entities.uri.AAIUriFactory
30 import org.onap.so.rest.APIResponse
31 import org.springframework.web.util.UriUtils
32 import org.onap.so.logger.MessageEnum
33 import org.onap.so.logger.MsoLogger
38 public class UpdateAAIVfModule extends AbstractServiceTaskProcessor {
39 private static final MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL, UpdateAAIVfModule.class);
42 private XmlParser xmlParser = new XmlParser()
43 ExceptionUtil exceptionUtil = new ExceptionUtil()
46 * Initialize the flow's variables.
48 * @param execution The flow's execution instance.
50 public void initProcessVariables(DelegateExecution execution) {
51 execution.setVariable('prefix', 'UAAIVfMod_')
52 execution.setVariable('UAAIVfMod_vnfId', null)
53 execution.setVariable('UAAIVfMod_vfModuleId', null)
54 execution.setVariable('UAAIVfMod_orchestrationStatus', null)
55 execution.setVariable('UAAIVfMod_heatStackId', null)
56 execution.setVariable('UAAIVfMod_volumeGroupId', null)
57 execution.setVariable('UAAIVfMod_getVfModuleResponseCode' ,null)
58 execution.setVariable('UAAIVfMod_getVfModuleResponse', '')
59 execution.setVariable('UAAIVfMod_updateVfModuleResponseCode', null)
60 execution.setVariable('UAAIVfMod_updateVfModuleResponse', '')
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('UpdateAAIVfModuleRequest')
76 msoLogger.debug('Received request xml:\n' + xml)
77 initProcessVariables(execution)
79 def vnfId = getRequiredNodeText(execution, xml,'vnf-id')
80 execution.setVariable('UAAIVfMod_vnfId', vnfId)
82 def vfModuleId = getRequiredNodeText(execution, xml,'vf-module-id')
83 execution.setVariable('UAAIVfMod_vfModuleId', vfModuleId)
85 msoLogger.trace('Exited ' + method)
86 } catch (BpmnError e) {
88 } catch (Exception e) {
90 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in preProcessRequest(): ' + e.getMessage())
95 * Using the received vnfId and vfModuleId, query AAI to get the corresponding VF Module.
96 * A 200 response is expected with the VF Module in the response body.
98 * @param execution The flow's execution instance.
100 public void getVfModule(DelegateExecution execution) {
101 def method = getClass().getSimpleName() + '.getVfModule(' +
102 'execution=' + execution.getId() +
104 msoLogger.trace('Entered ' + method)
107 def vnfId = execution.getVariable('UAAIVfMod_vnfId')
108 def vfModuleId = execution.getVariable('UAAIVfMod_vfModuleId')
110 AaiUtil aaiUriUtil = new AaiUtil(this)
111 AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.VF_MODULE, vnfId, vfModuleId)
112 String endPoint = aaiUriUtil.createAaiUri(uri)
115 msoLogger.debug('sending GET to AAI endpoint \'' + endPoint + '\'')
116 msoLogger.debug("UpdateAAIVfModule sending GET to AAI endpoint: " + endPoint)
118 APIResponse response = aaiUriUtil.executeAAIGetCall(execution, endPoint)
119 def responseData = response.getResponseBodyAsString()
120 execution.setVariable('UAAIVfMod_getVfModuleResponseCode', response.getStatusCode())
121 execution.setVariable('UAAIVfMod_getVfModuleResponse', responseData)
122 msoLogger.debug('Response code:' + response.getStatusCode())
123 msoLogger.debug('Response:' + System.lineSeparator() + responseData)
124 msoLogger.debug("UpdateAAIVfModule response data: " + responseData)
125 } catch (Exception ex) {
127 msoLogger.debug('Exception occurred while executing AAI GET:' + ex.getMessage())
128 execution.setVariable('UAAIVfMod_getVfModuleResponseCode', 500)
129 execution.setVariable('UAAIVfMod_getVfModuleResponse', 'AAI GET Failed:' + ex.getMessage())
131 msoLogger.trace('Exited ' + method)
132 } catch (BpmnError e) {
134 } catch (Exception e) {
136 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in getVfModule(): ' + e.getMessage())
141 * Construct and send a PATCH request to AAI to update the VF Module.
143 * @param execution The flow's execution instance.
145 public void updateVfModule(DelegateExecution execution) {
146 def method = getClass().getSimpleName() + '.updateVfModule(' +
147 'execution=' + execution.getId() +
149 msoLogger.trace('Entered ' + method)
152 def vnfId = execution.getVariable('UAAIVfMod_vnfId')
153 def vfModuleId = execution.getVariable('UAAIVfMod_vfModuleId')
154 def vfModule = execution.getVariable('UAAIVfMod_getVfModuleResponse')
155 def origRequest = execution.getVariable('UpdateAAIVfModuleRequest')
156 def Node vfModuleNode = xmlParser.parseText(vfModule)
158 msoLogger.debug("UpdateAAIVfModule request: " + origRequest)
159 // Confirm resource-version is in retrieved VF Module
160 if (utils.getChildNode(vfModuleNode, 'resource-version') == null) {
161 def msg = 'Can\'t update VF Module ' + vfModuleId + ' since \'resource-version\' is missing'
162 msoLogger.error(msg);
163 throw new Exception(msg)
166 // Handle persona-model-id/persona-model-version
167 def boolean doPersonaModelVersion = true
168 def String newPersonaModelId = utils.getNodeText(origRequest, 'persona-model-id')
169 def String newPersonaModelVersion = utils.getNodeText(origRequest, 'persona-model-version')
170 if ((newPersonaModelId == null) || (newPersonaModelVersion == null)) {
171 doPersonaModelVersion = false
173 // Confirm "new" persona-model-id is same as "current" persona-model-id
174 def String currPersonaModelId = utils.getChildNodeText(vfModuleNode, 'model-invariant-id')
175 if (currPersonaModelId == null) {
176 // check the old attribute name
177 currPersonaModelId = utils.getChildNodeText(vfModuleNode, 'model-version-id')
179 if (currPersonaModelId == null) {
180 currPersonaModelId = ''
182 if (!newPersonaModelId.equals(currPersonaModelId)) {
183 def msg = 'Can\'t update VF Module ' + vfModuleId + ' since there is \'persona-model-id\' mismatch between the current and new values'
185 throw new Exception(msg)
190 String orchestrationStatusEntry = updateVfModuleNode(origRequest, vfModuleNode, 'orchestration-status')
191 String heatStackIdEntry = updateVfModuleNode(origRequest, vfModuleNode, 'heat-stack-id')
192 String personaModelVersionEntry = ""
193 if (doPersonaModelVersion) {
194 personaModelVersionEntry = updateVfModuleNode(origRequest, vfModuleNode, 'persona-model-version')
196 String contrailServiceInstanceFqdnEntry = updateVfModuleNode(origRequest, vfModuleNode, 'contrail-service-instance-fqdn')
198 { ${orchestrationStatusEntry}
200 ${personaModelVersionEntry}
201 ${contrailServiceInstanceFqdnEntry}
202 "vf-module-id": "${vfModuleId}"
206 AaiUtil aaiUriUtil = new AaiUtil(this)
207 AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.VF_MODULE, vnfId, vfModuleId)
208 String endPoint = aaiUriUtil.createAaiUri(uri)
211 msoLogger.debug('sending PATCH to AAI endpoint \'' + endPoint + '\'' + 'with payload \n' + payload)
212 msoLogger.debug("Sending PATCH to AAI endpoint: " + endPoint)
214 APIResponse response = aaiUriUtil.executeAAIPatchCall(execution, endPoint, payload)
215 def responseData = response.getResponseBodyAsString()
216 execution.setVariable('UAAIVfMod_updateVfModuleResponseCode', response.getStatusCode())
217 execution.setVariable('UAAIVfMod_updateVfModuleResponse', responseData)
218 msoLogger.debug("UpdateAAIVfModule Response data: " + responseData)
219 msoLogger.debug('Response code:' + response.getStatusCode())
220 msoLogger.debug('Response:' + System.lineSeparator() + responseData)
221 } catch (Exception ex) {
223 msoLogger.debug('Exception occurred while executing AAI PATCH:' + ex.getMessage())
224 execution.setVariable('UAAIVfMod_updateVfModuleResponseCode', 500)
225 execution.setVariable('UAAIVfMod_updateVfModuleResponse', 'AAI PATCH Failed:' + ex.getMessage())
227 msoLogger.trace('Exited ' + method)
228 } catch (BpmnError e) {
230 } catch (Exception e) {
232 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in updateVfModule(): ' + e.getMessage())
237 * Sets up json attributes for PATCH request for Update
239 * @param origRequest Incoming update request with VF Module elements to be updated.
240 * @param vfModule Current VF Module retrieved from AAI.
241 * @param element Name of element to be inserted.
243 private String updateVfModuleNode(String origRequest, Node vfModuleNode, String elementName) {
245 if (!utils.nodeExists(origRequest, elementName)) {
248 def elementValue = utils.getNodeText(origRequest, elementName)
250 if (elementValue.equals('DELETE')) {
251 // Set the element being deleted to null
252 return """"${elementName}": null,"""
255 return """"${elementName}": "${elementValue}","""
261 * Check the Volume Group ID from the incoming update request against the Volume Group ID from the
262 * given VF Module. If they are equal or if they are both 'null', then that is acceptable and 'null'
263 * is returned. Otherwise a message describing how the values are unacceptable/incompatible is returned.
265 * @param origRequest Incoming update request with VF Module elements to be updated.
266 * @param vfModuleNode VF Module (as a Node) retrieved from AAI.
267 * @param isDebugLogEnabled Is DEBUG log enabled?
268 * @return 'null' if the Volume Group IDs are acceptable. Otherwise return a message describing how the
269 * values are unacceptable/incompatible.
271 private String checkVolumeGroupId(String origRequest, Node vfModuleNode, String isDebugLogEnabled) {
272 def requestVolumeGroupId = utils.getNodeText(origRequest, 'volume-group-id')
273 def currVolumeGroupId = getCurrVolumeGroupId(vfModuleNode)
275 msoLogger.debug('Check volume-group-id: volume-group-id in original request is \'' + requestVolumeGroupId + '\', volume-group-id from VF Module is \'' + currVolumeGroupId + '\'')
279 if (requestVolumeGroupId == null) {
280 if (currVolumeGroupId == null) {
283 result = 'Cannot detach a volume group from an existing VF Module'
286 if (currVolumeGroupId == null) {
287 result = 'Cannot add a volume gruop to an existing VF Module'
289 if (!requestVolumeGroupId.equals(currVolumeGroupId)) {
290 result = 'Cannot change the volume group on an existing VF Module'
299 * Find and return the value of the Volume Group ID for the specified VF Module. If
300 * the value of the Volume Group ID cannot be found for any reason, 'null' is returned.
302 * @param vfModuleNode VF Module (as a Node) retrieved from AAI.
303 * @return the value of the Volume Group ID for the specified VF Module. If the
304 * value of the Volume Group ID cannot be found for any reason, 'null' is returned.
306 private String getCurrVolumeGroupId(Node vfModuleNode) {
307 def Node relationshipList = utils.getChildNode(vfModuleNode, 'relationship-list')
308 if (relationshipList == null) {
311 def NodeList relationships = utils.getIdenticalChildren(relationshipList, 'relationship')
312 for (Node relationshipNode in relationships) {
313 def String relatedTo = utils.getChildNodeText(relationshipNode, 'related-to')
314 if ((relatedTo != null) && relatedTo.equals('volume-group')) {
315 def NodeList relationshipDataList = utils.getIdenticalChildren(relationshipNode, 'relationship-data')
316 for (Node relationshipDataNode in relationshipDataList) {
317 def String relationshipKey = utils.getChildNodeText(relationshipDataNode, 'relationship-key')
318 if ((relationshipKey != null) && relationshipKey.equals('volume-group.volume-group-id')) {
319 return utils.getChildNodeText(relationshipDataNode, 'relationship-value')
328 * Generates a WorkflowException if the AAI query returns a response code other than 200.
330 * @param execution The flow's execution instance.
332 public void handleAAIQueryFailure(DelegateExecution execution) {
333 def method = getClass().getSimpleName() + '.handleAAIQueryFailure(' +
334 'execution=' + execution.getId() +
336 msoLogger.trace('Entered ' + method)
338 msoLogger.error( 'Error occurred attempting to query AAI, Response Code ' + execution.getVariable('UAAIVfMod_getVfModuleResponseCode'));
339 String processKey = getProcessKey(execution);
340 WorkflowException exception = new WorkflowException(processKey, 5000,
341 execution.getVariable('UAAIVfMod_getVfModuleResponse'))
342 execution.setVariable('WorkflowException', exception)
343 msoLogger.debug("UpdateAAIVfModule query failure: " + exception.getErrorMessage())
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('UAAIVfMod_updateVfModuleResponseCode'));
359 String processKey = getProcessKey(execution);
360 WorkflowException exception = new WorkflowException(processKey, 5000,
361 execution.getVariable('UAAIVfMod_updateVfModuleResponse'))
362 execution.setVariable('WorkflowException', exception)
364 msoLogger.debug("UpdateAAIVfModule failure: " + exception.getErrorMessage())
365 msoLogger.trace('Exited ' + method)