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 com.att.bpm.scripts
23 import groovy.util.Node
24 import groovy.util.XmlParser;
25 import groovy.xml.QName
27 import java.io.Serializable;
29 import org.camunda.bpm.engine.delegate.BpmnError
30 import org.camunda.bpm.engine.runtime.Execution
31 import org.springframework.web.util.UriUtils
33 import org.openecomp.mso.rest.APIResponse
34 import org.openecomp.mso.rest.RESTClient
35 import org.openecomp.mso.rest.RESTConfig
36 import org.openecomp.mso.bpmn.core.RollbackData
37 import org.openecomp.mso.bpmn.core.WorkflowException
40 public class UpdateAAIVfModule extends AbstractServiceTaskProcessor {
42 private XmlParser xmlParser = new XmlParser()
45 * Initialize the flow's variables.
47 * @param execution The flow's execution instance.
49 public void initProcessVariables(Execution execution) {
50 execution.setVariable('prefix', 'UAAIVfMod_')
51 execution.setVariable('UAAIVfMod_vnfId', null)
52 execution.setVariable('UAAIVfMod_vfModuleId', null)
53 execution.setVariable('UAAIVfMod_orchestrationStatus', null)
54 execution.setVariable('UAAIVfMod_heatStackId', null)
55 execution.setVariable('UAAIVfMod_volumeGroupId', null)
56 execution.setVariable('UAAIVfMod_getVfModuleResponseCode' ,null)
57 execution.setVariable('UAAIVfMod_getVfModuleResponse', '')
58 execution.setVariable('UAAIVfMod_updateVfModuleResponseCode', null)
59 execution.setVariable('UAAIVfMod_updateVfModuleResponse', '')
63 * Check for missing elements in the received request.
65 * @param execution The flow's execution instance.
67 public void preProcessRequest(Execution execution) {
68 def method = getClass().getSimpleName() + '.preProcessRequest(' +
69 'execution=' + execution.getId() +
71 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
72 logDebug('Entered ' + method, isDebugLogEnabled)
75 def xml = execution.getVariable('UpdateAAIVfModuleRequest')
76 logDebug('Received request xml:\n' + xml, isDebugLogEnabled)
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 logDebug('Exited ' + method, isDebugLogEnabled)
86 } catch (BpmnError e) {
88 } catch (Exception e) {
89 logError('Caught exception in ' + method, e)
90 createWorkflowException(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(Execution execution) {
101 def method = getClass().getSimpleName() + '.getVfModule(' +
102 'execution=' + execution.getId() +
104 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
105 logDebug('Entered ' + method, isDebugLogEnabled)
108 def vnfId = execution.getVariable('UAAIVfMod_vnfId')
109 def vfModuleId = execution.getVariable('UAAIVfMod_vfModuleId')
111 // Construct endpoint
112 AaiUtil aaiUriUtil = new AaiUtil(this)
113 def aai_uri = aaiUriUtil.getNetworkGenericVnfUri(execution)
114 logDebug('AAI URI is: ' + aai_uri, isDebugLogEnabled)
115 String endPoint = execution.getVariable('URN_aai_endpoint') + aai_uri + '/' + UriUtils.encode(vnfId, "UTF-8") + '/vf-modules/vf-module/' + UriUtils.encode(vfModuleId, "UTF-8")
117 String basicAuthCred = utils.getBasicAuth(execution.getVariable("URN_aai_auth"),execution.getVariable("URN_mso_msoKey"))
120 RESTConfig config = new RESTConfig(endPoint);
121 def responseData = ''
122 def aaiRequestId = UUID.randomUUID().toString()
123 RESTClient client = new RESTClient(config).
124 addHeader('X-TransactionId', aaiRequestId).
125 addHeader('X-FromAppId', 'MSO').
126 addHeader('Content-Type', 'application/xml').
127 addHeader('Accept','application/xml');
128 if (basicAuthCred != null && !"".equals(basicAuthCred)) {
129 client.addAuthorizationHeader(basicAuthCred)
132 logDebug('sending GET to AAI endpoint \'' + endPoint + '\'', isDebugLogEnabled)
133 APIResponse response = client.httpGet()
135 responseData = response.getResponseBodyAsString()
136 execution.setVariable('UAAIVfMod_getVfModuleResponseCode', response.getStatusCode())
137 execution.setVariable('UAAIVfMod_getVfModuleResponse', responseData)
138 logDebug('Response code:' + response.getStatusCode(), isDebugLogEnabled)
139 logDebug('Response:' + System.lineSeparator() + responseData, isDebugLogEnabled)
140 } catch (Exception ex) {
142 logDebug('Exception occurred while executing AAI GET:' + ex.getMessage(),isDebugLogEnabled)
143 execution.setVariable('UAAIVfMod_getVfModuleResponseCode', 500)
144 execution.setVariable('UAAIVfMod_getVfModuleResponse', 'AAI GET Failed:' + ex.getMessage())
146 logDebug('Exited ' + method, isDebugLogEnabled)
147 } catch (BpmnError e) {
149 } catch (Exception e) {
150 logError('Caught exception in ' + method, e)
151 createWorkflowException(execution, 1002, 'Error in getVfModule(): ' + e.getMessage())
156 * Construct and send a PUT request to AAI to update the VF Module.
158 * @param execution The flow's execution instance.
160 public void updateVfModule(Execution execution) {
161 def method = getClass().getSimpleName() + '.updateVfModule(' +
162 'execution=' + execution.getId() +
164 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
165 logDebug('Entered ' + method, isDebugLogEnabled)
168 def vnfId = execution.getVariable('UAAIVfMod_vnfId')
169 def vfModuleId = execution.getVariable('UAAIVfMod_vfModuleId')
170 def vfModule = execution.getVariable('UAAIVfMod_getVfModuleResponse')
171 def origRequest = execution.getVariable('UpdateAAIVfModuleRequest')
172 def Node vfModuleNode = xmlParser.parseText(vfModule)
174 // Confirm resource-version is in retrieved VF Module
175 if (utils.getChildNode(vfModuleNode, 'resource-version') == null) {
176 def msg = 'Can\'t update VF Module ' + vfModuleId + ' since \'resource-version\' is missing'
178 throw new Exception(msg)
181 // TEMPORARY!!! Disable Volume Group Check
182 // Check volume-group-id conditions
183 //def checkVgiResult = checkVolumeGroupId(origRequest, vfModuleNode, isDebugLogEnabled)
184 //if (checkVgiResult != null) {
185 // def msg = 'Can\'t update VF Module ' + vfModuleId + ': ' + checkVgiResult
187 // throw new Exception(msg)
190 // Handle persona-model-id/persona-model-version
191 def boolean doPersonaModelVersion = true
192 def String newPersonaModelId = utils.getNodeText1(origRequest, 'persona-model-id')
193 def String newPersonaModelVersion = utils.getNodeText1(origRequest, 'persona-model-version')
194 if ((newPersonaModelId == null) || (newPersonaModelVersion == null)) {
195 doPersonaModelVersion = false
197 // Confirm "new" persona-model-id is same as "current" persona-model-id
198 def String currPersonaModelId = utils.getChildNodeText(vfModuleNode, 'persona-model-id')
199 if (currPersonaModelId == null) {
200 currPersonaModelId = ''
202 if (!newPersonaModelId.equals(currPersonaModelId)) {
203 def msg = 'Can\'t update VF Module ' + vfModuleId + ' since there is \'persona-model-id\' mismatch between the current and new values'
205 throw new Exception(msg)
210 updateVfModuleNode(origRequest, vfModuleNode, 'orchestration-status')
211 updateVfModuleNode(origRequest, vfModuleNode, 'heat-stack-id')
212 if (doPersonaModelVersion) {
213 updateVfModuleNode(origRequest, vfModuleNode, 'persona-model-version')
215 updateVfModuleNode(origRequest, vfModuleNode, 'contrail-service-instance-fqdn')
216 def payload = utils.nodeToString(vfModuleNode)
218 // Construct endpoint
219 AaiUtil aaiUriUtil = new AaiUtil(this)
220 def aai_uri = aaiUriUtil.getNetworkGenericVnfUri(execution)
221 logDebug('AAI URI is: ' + aai_uri, isDebugLogEnabled)
222 String endPoint = execution.getVariable('URN_aai_endpoint') + aai_uri + '/' + UriUtils.encode(vnfId, "UTF-8") + '/vf-modules/vf-module/' + UriUtils.encode(vfModuleId, "UTF-8")
224 String basicAuthCred = utils.getBasicAuth(execution.getVariable("URN_aai_auth"),execution.getVariable("URN_mso_msoKey"))
227 RESTConfig config = new RESTConfig(endPoint);
228 def responseData = ''
229 def aaiRequestId = UUID.randomUUID().toString()
230 RESTClient client = new RESTClient(config).
231 addHeader('X-TransactionId', aaiRequestId).
232 addHeader('X-FromAppId', 'MSO').
233 addHeader('Content-Type', 'application/xml').
234 addHeader('Accept','application/xml');
235 if (basicAuthCred != null && !"".equals(basicAuthCred)) {
236 client.addAuthorizationHeader(basicAuthCred)
239 logDebug('sending PUT to AAI endpoint \'' + endPoint + '\'' + 'with payload \n' + payload, isDebugLogEnabled)
240 APIResponse response = client.httpPut(payload)
242 responseData = response.getResponseBodyAsString()
243 execution.setVariable('UAAIVfMod_updateVfModuleResponseCode', response.getStatusCode())
244 execution.setVariable('UAAIVfMod_updateVfModuleResponse', responseData)
245 logDebug('Response code:' + response.getStatusCode(), isDebugLogEnabled)
246 logDebug('Response:' + System.lineSeparator() + responseData, isDebugLogEnabled)
247 } catch (Exception ex) {
249 logDebug('Exception occurred while executing AAI PUT:' + ex.getMessage(),isDebugLogEnabled)
250 execution.setVariable('UAAIVfMod_updateVfModuleResponseCode', 500)
251 execution.setVariable('UAAIVfMod_updateVfModuleResponse', 'AAI PUT Failed:' + ex.getMessage())
253 logDebug('Exited ' + method, isDebugLogEnabled)
254 } catch (BpmnError e) {
256 } catch (Exception e) {
257 logError('Caught exception in ' + method, e)
258 createWorkflowException(execution, 1002, 'Error in updateVfModule(): ' + e.getMessage())
263 * Insert a new Node, replace the value of an existing Node, or delete an existing Node in the current
264 * VF Module Node, as necessary.
266 * If the Node with the same name already exists in current VF Module, but is not being updated, then do
267 * nothing. If the element is being updated and it already exists in the current VF Module, then check
268 * the value specified in the original request. If the value is 'DELETE', remove that Node from the
269 * current VF Module. Otherwise, change the value to the specified new value. If the element is
270 * being updated but doesn't exist in the current VF Module, and the new value is not 'DELETE', then
271 * create an appropriate new node and add it to the VF Module.
273 * @param origRequest Incoming update request with VF Module elements to be updated.
274 * @param vfModule Current VF Module retrieved from AAI.
275 * @param element Name of element to be inserted.
277 private void updateVfModuleNode(String origRequest, Node vfModuleNode, String elementName) {
279 if (!utils.nodeExists(origRequest, elementName)) {
282 def elementValue = utils.getNodeText(origRequest, elementName)
284 def Node childNode = utils.getChildNode(vfModuleNode, elementName)
285 if (childNode == null) {
286 if (elementValue.equals('DELETE')) {
287 // Element doesn't exist but is being deleted, so do nothing
290 // Node doesn't exist, create a new Node as a child
291 new Node(vfModuleNode, elementName, elementValue)
293 if (elementValue.equals('DELETE')) {
294 // Node exists, but should be deleted
295 vfModuleNode.remove(childNode)
297 // Node already exists, just give it a new value
298 childNode.setValue(elementValue)
304 * Check the Volume Group ID from the incoming update request against the Volume Group ID from the
305 * given VF Module. If they are equal or if they are both 'null', then that is acceptable and 'null'
306 * is returned. Otherwise a message describing how the values are unacceptable/incompatible is returned.
308 * @param origRequest Incoming update request with VF Module elements to be updated.
309 * @param vfModuleNode VF Module (as a Node) retrieved from AAI.
310 * @param isDebugLogEnabled Is DEBUG log enabled?
311 * @return 'null' if the Volume Group IDs are acceptable. Otherwise return a message describing how the
312 * values are unacceptable/incompatible.
314 private String checkVolumeGroupId(String origRequest, Node vfModuleNode, String isDebugLogEnabled) {
315 def requestVolumeGroupId = utils.getNodeText1(origRequest, 'volume-group-id')
316 def currVolumeGroupId = getCurrVolumeGroupId(vfModuleNode)
318 logDebug('Check volume-group-id: volume-group-id in original request is \'' + requestVolumeGroupId +
319 '\', volume-group-id from VF Module is \'' + currVolumeGroupId + '\'', isDebugLogEnabled)
323 if (requestVolumeGroupId == null) {
324 if (currVolumeGroupId == null) {
327 result = 'Cannot detach a volume group from an existing VF Module'
330 if (currVolumeGroupId == null) {
331 result = 'Cannot add a volume gruop to an existing VF Module'
333 if (!requestVolumeGroupId.equals(currVolumeGroupId)) {
334 result = 'Cannot change the volume group on an existing VF Module'
343 * Find and return the value of the Volume Group ID for the specified VF Module. If
344 * the value of the Volume Group ID cannot be found for any reason, 'null' is returned.
346 * @param vfModuleNode VF Module (as a Node) retrieved from AAI.
347 * @return the value of the Volume Group ID for the specified VF Module. If the
348 * value of the Volume Group ID cannot be found for any reason, 'null' is returned.
350 private String getCurrVolumeGroupId(Node vfModuleNode) {
351 def Node relationshipList = utils.getChildNode(vfModuleNode, 'relationship-list')
352 if (relationshipList == null) {
355 def NodeList relationships = utils.getIdenticalChildren(relationshipList, 'relationship')
356 for (Node relationshipNode in relationships) {
357 def String relatedTo = utils.getChildNodeText(relationshipNode, 'related-to')
358 if ((relatedTo != null) && relatedTo.equals('volume-group')) {
359 def NodeList relationshipDataList = utils.getIdenticalChildren(relationshipNode, 'relationship-data')
360 for (Node relationshipDataNode in relationshipDataList) {
361 def String relationshipKey = utils.getChildNodeText(relationshipDataNode, 'relationship-key')
362 if ((relationshipKey != null) && relationshipKey.equals('volume-group.volume-group-id')) {
363 return utils.getChildNodeText(relationshipDataNode, 'relationship-value')
372 * Generates a WorkflowException if the AAI query returns a response code other than 200.
374 * @param execution The flow's execution instance.
376 public void handleAAIQueryFailure(Execution execution) {
377 def method = getClass().getSimpleName() + '.handleAAIQueryFailure(' +
378 'execution=' + execution.getId() +
380 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
381 logDebug('Entered ' + method, isDebugLogEnabled)
383 logError('Error occurred attempting to query AAI, Response Code ' +
384 execution.getVariable('UAAIVfMod_getVfModuleResponseCode') + ', Error Response ' +
385 execution.getVariable('UAAIVfMod_getVfModuleResponse'))
386 String processKey = getProcessKey(execution);
387 WorkflowException exception = new WorkflowException(processKey, 5000,
388 execution.getVariable('UAAIVfMod_getVfModuleResponse'))
389 execution.setVariable('WorkflowException', exception)
391 logDebug('Exited ' + method, isDebugLogEnabled)
395 * Generates a WorkflowException if updating a VF Module in AAI returns a response code other than 200.
397 * @param execution The flow's execution instance.
399 public void handleUpdateVfModuleFailure(Execution execution) {
400 def method = getClass().getSimpleName() + '.handleUpdateVfModuleFailure(' +
401 'execution=' + execution.getId() +
403 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
404 logDebug('Entered ' + method, isDebugLogEnabled)
406 logError('Error occurred attempting to update VF Module in AAI, Response Code ' +
407 execution.getVariable('UAAIVfMod_updateVfModuleResponseCode') + ', Error Response ' +
408 execution.getVariable('UAAIVfMod_updateVfModuleResponse'))
409 String processKey = getProcessKey(execution);
410 WorkflowException exception = new WorkflowException(processKey, 5000,
411 execution.getVariable('UAAIVfMod_updateVfModuleResponse'))
412 execution.setVariable('WorkflowException', exception)
414 logDebug('Exited ' + method, isDebugLogEnabled)