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 javax.ws.rs.NotFoundException
25 import org.camunda.bpm.engine.delegate.BpmnError
26 import org.camunda.bpm.engine.delegate.DelegateExecution
27 import org.onap.so.bpmn.core.WorkflowException
28 import org.onap.so.client.aai.AAIObjectType
29 import org.onap.so.client.aai.entities.uri.AAIResourceUri
30 import org.onap.so.client.aai.entities.uri.AAIUriFactory
31 import org.onap.so.logger.MsoLogger
34 public class UpdateAAIVfModule extends AbstractServiceTaskProcessor {
35 private static final MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL, UpdateAAIVfModule.class);
38 private XmlParser xmlParser = new XmlParser()
39 ExceptionUtil exceptionUtil = new ExceptionUtil()
42 * Initialize the flow's variables.
44 * @param execution The flow's execution instance.
46 public void initProcessVariables(DelegateExecution execution) {
47 execution.setVariable('prefix', 'UAAIVfMod_')
48 execution.setVariable('UAAIVfMod_vnfId', null)
49 execution.setVariable('UAAIVfMod_vfModuleId', null)
50 execution.setVariable('UAAIVfMod_orchestrationStatus', null)
51 execution.setVariable('UAAIVfMod_heatStackId', null)
52 execution.setVariable('UAAIVfMod_volumeGroupId', null)
53 execution.setVariable('UAAIVfMod_getVfModuleResponseCode' ,null)
54 execution.setVariable('UAAIVfMod_getVfModuleResponse', '')
55 execution.setVariable('UAAIVfMod_updateVfModuleResponseCode', null)
56 execution.setVariable('UAAIVfMod_updateVfModuleResponse', '')
60 * Check for missing elements in the received request.
62 * @param execution The flow's execution instance.
64 public void preProcessRequest(DelegateExecution execution) {
65 def method = getClass().getSimpleName() + '.preProcessRequest(' +
66 'execution=' + execution.getId() +
68 msoLogger.trace('Entered ' + method)
71 def xml = execution.getVariable('UpdateAAIVfModuleRequest')
72 msoLogger.debug('Received request xml:\n' + xml)
73 initProcessVariables(execution)
75 def vnfId = getRequiredNodeText(execution, xml,'vnf-id')
76 execution.setVariable('UAAIVfMod_vnfId', vnfId)
78 def vfModuleId = getRequiredNodeText(execution, xml,'vf-module-id')
79 execution.setVariable('UAAIVfMod_vfModuleId', vfModuleId)
81 msoLogger.trace('Exited ' + method)
82 } catch (BpmnError e) {
84 } catch (Exception e) {
86 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in preProcessRequest(): ' + e.getMessage())
91 * Using the received vnfId and vfModuleId, query AAI to get the corresponding VF Module.
92 * A 200 response is expected with the VF Module in the response body.
94 * @param execution The flow's execution instance.
96 public void getVfModule(DelegateExecution execution) {
97 def method = getClass().getSimpleName() + '.getVfModule(' +
98 'execution=' + execution.getId() +
100 msoLogger.trace('Entered ' + method)
103 def vnfId = execution.getVariable('UAAIVfMod_vnfId')
104 def vfModuleId = execution.getVariable('UAAIVfMod_vfModuleId')
106 AAIResourceUri resourceUri = AAIUriFactory.createResourceUri(AAIObjectType.VF_MODULE, vnfId, vfModuleId);
107 Optional<org.onap.aai.domain.yang.VfModule> vfModule = getAAIClient().get(org.onap.aai.domain.yang.VfModule.class, resourceUri)
108 if (vfModule.isPresent()) {
109 execution.setVariable('UAAIVfMod_getVfModuleResponseCode', 200)
110 execution.setVariable('UAAIVfMod_getVfModuleResponse', vfModule.get())
112 execution.setVariable('UAAIVfMod_getVfModuleResponseCode', 404)
113 execution.setVariable('UAAIVfMod_getVfModuleResponse', "VF Module not found in AAI")
115 } catch (Exception ex) {
116 msoLogger.debug('Exception occurred while executing AAI GET:' + ex.getMessage())
117 execution.setVariable('UAAIVfMod_getVfModuleResponseCode', 500)
118 execution.setVariable('UAAIVfMod_getVfModuleResponse', 'AAI GET Failed:' + ex.getMessage())
120 } catch (BpmnError e) {
122 } catch (Exception e) {
124 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in getVfModule(): ' + e.getMessage())
129 * Construct and send a PATCH request to AAI to update the VF Module.
131 * @param execution The flow's execution instance.
133 public void updateVfModule(DelegateExecution execution) {
134 def method = getClass().getSimpleName() + '.updateVfModule(' +
135 'execution=' + execution.getId() +
137 msoLogger.trace('Entered ' + method)
140 def vnfId = execution.getVariable('UAAIVfMod_vnfId')
141 def vfModuleId = execution.getVariable('UAAIVfMod_vfModuleId')
142 org.onap.aai.domain.yang.VfModule vfModule = execution.getVariable('UAAIVfMod_getVfModuleResponse')
143 def origRequest = execution.getVariable('UpdateAAIVfModuleRequest')
145 msoLogger.debug("UpdateAAIVfModule request: " + origRequest)
146 // Handle persona-model-id/persona-model-version
147 def boolean doPersonaModelVersion = true
148 def String newPersonaModelId = utils.getNodeText(origRequest, 'persona-model-id')
149 def String newPersonaModelVersion = utils.getNodeText(origRequest, 'persona-model-version')
150 if ((newPersonaModelId == null) || (newPersonaModelVersion == null)) {
151 doPersonaModelVersion = false
153 // Confirm "new" persona-model-id is same as "current" persona-model-id
154 def String currPersonaModelId = vfModule.getModelInvariantId()
155 if (currPersonaModelId == null) {
156 // check the old attribute name
157 currPersonaModelId = vfModule.getModelVersionId()
159 if (currPersonaModelId == null) {
160 currPersonaModelId = ''
162 if (!newPersonaModelId.equals(currPersonaModelId)) {
163 def msg = 'Can\'t update VF Module ' + vfModuleId + ' since there is \'persona-model-id\' mismatch between the current and new values'
165 throw new Exception(msg)
170 String orchestrationStatusEntry = updateVfModuleNode(origRequest , 'orchestration-status')
171 String heatStackIdEntry = updateVfModuleNode(origRequest, 'heat-stack-id')
172 String personaModelVersionEntry = ""
173 if (doPersonaModelVersion) {
174 personaModelVersionEntry = updateVfModuleNode(origRequest, 'persona-model-version')
176 String contrailServiceInstanceFqdnEntry = updateVfModuleNode(origRequest, 'contrail-service-instance-fqdn')
178 { ${orchestrationStatusEntry}
180 ${personaModelVersionEntry}
181 ${contrailServiceInstanceFqdnEntry}
182 "vf-module-id": "${vfModuleId}"
187 AAIResourceUri resourceUri = AAIUriFactory.createResourceUri(AAIObjectType.VF_MODULE, vnfId, vfModuleId)
188 getAAIClient().update(resourceUri, payload)
189 }catch(NotFoundException ignored){
190 msoLogger.debug("VF-Module not found!!")
191 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "vf-module " + vfModuleId + " not found for under vnf " + vnfId + " in A&AI!")
194 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, 'Exception occurred while executing AAI PATCH:' + ex.getMessage())
196 } catch (BpmnError e) {
198 } catch (Exception e) {
200 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in updateVfModule(): ' + e.getMessage())
205 * Sets up json attributes for PATCH request for Update
207 * @param origRequest Incoming update request with VF Module elements to be updated.
208 * @param element Name of element to be inserted.
210 private String updateVfModuleNode(String origRequest, String elementName) {
212 if (!utils.nodeExists(origRequest, elementName)) {
215 def elementValue = utils.getNodeText(origRequest, elementName)
217 if (elementValue.equals('DELETE')) {
218 // Set the element being deleted to null
219 return """"${elementName}": null,"""
222 return """"${elementName}": "${elementValue}","""
228 * Check the Volume Group ID from the incoming update request against the Volume Group ID from the
229 * given VF Module. If they are equal or if they are both 'null', then that is acceptable and 'null'
230 * is returned. Otherwise a message describing how the values are unacceptable/incompatible is returned.
232 * @param origRequest Incoming update request with VF Module elements to be updated.
233 * @param vfModuleNode VF Module (as a Node) retrieved from AAI.
234 * @param isDebugLogEnabled Is DEBUG log enabled?
235 * @return 'null' if the Volume Group IDs are acceptable. Otherwise return a message describing how the
236 * values are unacceptable/incompatible.
238 private String checkVolumeGroupId(String origRequest, Node vfModuleNode, String isDebugLogEnabled) {
239 def requestVolumeGroupId = utils.getNodeText(origRequest, 'volume-group-id')
240 def currVolumeGroupId = getCurrVolumeGroupId(vfModuleNode)
242 msoLogger.debug('Check volume-group-id: volume-group-id in original request is \'' + requestVolumeGroupId + '\', volume-group-id from VF Module is \'' + currVolumeGroupId + '\'')
246 if (requestVolumeGroupId == null) {
247 if (currVolumeGroupId == null) {
250 result = 'Cannot detach a volume group from an existing VF Module'
253 if (currVolumeGroupId == null) {
254 result = 'Cannot add a volume gruop to an existing VF Module'
256 if (!requestVolumeGroupId.equals(currVolumeGroupId)) {
257 result = 'Cannot change the volume group on an existing VF Module'
266 * Find and return the value of the Volume Group ID for the specified VF Module. If
267 * the value of the Volume Group ID cannot be found for any reason, 'null' is returned.
269 * @param vfModuleNode VF Module (as a Node) retrieved from AAI.
270 * @return the value of the Volume Group ID for the specified VF Module. If the
271 * value of the Volume Group ID cannot be found for any reason, 'null' is returned.
273 private String getCurrVolumeGroupId(Node vfModuleNode) {
274 def Node relationshipList = utils.getChildNode(vfModuleNode, 'relationship-list')
275 if (relationshipList == null) {
278 def NodeList relationships = utils.getIdenticalChildren(relationshipList, 'relationship')
279 for (Node relationshipNode in relationships) {
280 def String relatedTo = utils.getChildNodeText(relationshipNode, 'related-to')
281 if ((relatedTo != null) && relatedTo.equals('volume-group')) {
282 def NodeList relationshipDataList = utils.getIdenticalChildren(relationshipNode, 'relationship-data')
283 for (Node relationshipDataNode in relationshipDataList) {
284 def String relationshipKey = utils.getChildNodeText(relationshipDataNode, 'relationship-key')
285 if ((relationshipKey != null) && relationshipKey.equals('volume-group.volume-group-id')) {
286 return utils.getChildNodeText(relationshipDataNode, 'relationship-value')
295 * Generates a WorkflowException if the AAI query returns a response code other than 200.
297 * @param execution The flow's execution instance.
299 public void handleAAIQueryFailure(DelegateExecution execution) {
300 def method = getClass().getSimpleName() + '.handleAAIQueryFailure(' +
301 'execution=' + execution.getId() +
303 msoLogger.trace('Entered ' + method)
305 msoLogger.error( 'Error occurred attempting to query AAI, Response Code ' + execution.getVariable('UAAIVfMod_getVfModuleResponseCode'));
306 String processKey = getProcessKey(execution);
307 WorkflowException exception = new WorkflowException(processKey, 5000,
308 execution.getVariable('UAAIVfMod_getVfModuleResponse'))
309 execution.setVariable('WorkflowException', exception)
310 msoLogger.debug("UpdateAAIVfModule query failure: " + exception.getErrorMessage())
311 msoLogger.trace('Exited ' + method)