[MSO-8] Update the maven dependency
[so.git] / bpmn / MSOCommonBPMN / src / main / groovy / org / openecomp / mso / bpmn / common / scripts / UpdateAAIVfModule.groovy
1 /*-
2  * ============LICENSE_START=======================================================
3  * OPENECOMP - MSO
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
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
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=========================================================
19  */
20
21 package org.openecomp.mso.bpmn.common.scripts
22
23 import org.camunda.bpm.engine.delegate.BpmnError
24 import org.camunda.bpm.engine.runtime.Execution
25 import org.openecomp.mso.bpmn.core.WorkflowException
26 import org.openecomp.mso.rest.APIResponse
27 import org.springframework.web.util.UriUtils
28
29
30 public class UpdateAAIVfModule extends AbstractServiceTaskProcessor {
31
32         private XmlParser xmlParser = new XmlParser()
33
34         /**
35          * Initialize the flow's variables.
36          *
37          * @param execution The flow's execution instance.
38          */
39         public void initProcessVariables(Execution execution) {
40                 execution.setVariable('prefix', 'UAAIVfMod_')
41                 execution.setVariable('UAAIVfMod_vnfId', null)
42                 execution.setVariable('UAAIVfMod_vfModuleId', null)
43                 execution.setVariable('UAAIVfMod_orchestrationStatus', null)
44                 execution.setVariable('UAAIVfMod_heatStackId', null)
45                 execution.setVariable('UAAIVfMod_volumeGroupId', null)
46                 execution.setVariable('UAAIVfMod_getVfModuleResponseCode' ,null)
47                 execution.setVariable('UAAIVfMod_getVfModuleResponse', '')
48                 execution.setVariable('UAAIVfMod_updateVfModuleResponseCode', null)
49                 execution.setVariable('UAAIVfMod_updateVfModuleResponse', '')
50         }
51
52         /**
53          * Check for missing elements in the received request.
54          *
55          * @param execution The flow's execution instance.
56          */
57         public void preProcessRequest(Execution execution) {
58                 def method = getClass().getSimpleName() + '.preProcessRequest(' +
59                         'execution=' + execution.getId() +
60                         ')'
61                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
62                 logDebug('Entered ' + method, isDebugLogEnabled)
63
64                 try {
65                         def xml = execution.getVariable('UpdateAAIVfModuleRequest')
66                         logDebug('Received request xml:\n' + xml, isDebugLogEnabled)
67                         utils.logAudit("UpdateAAIVfModule Request XML: " + xml)
68                         initProcessVariables(execution)
69
70                         def vnfId = getRequiredNodeText(execution, xml,'vnf-id')
71                         execution.setVariable('UAAIVfMod_vnfId', vnfId)
72
73                         def vfModuleId = getRequiredNodeText(execution, xml,'vf-module-id')
74                         execution.setVariable('UAAIVfMod_vfModuleId', vfModuleId)
75
76                         logDebug('Exited ' + method, isDebugLogEnabled)
77                 } catch (BpmnError e) {
78                         throw e;
79                 } catch (Exception e) {
80                         logError('Caught exception in ' + method, e)
81                         createWorkflowException(execution, 1002, 'Error in preProcessRequest(): ' + e.getMessage())
82                 }
83         }
84
85         /**
86          * Using the received vnfId and vfModuleId, query AAI to get the corresponding VF Module.
87          * A 200 response is expected with the VF Module in the response body.
88          *
89          * @param execution The flow's execution instance.
90          */
91         public void getVfModule(Execution execution) {
92                 def method = getClass().getSimpleName() + '.getVfModule(' +
93                         'execution=' + execution.getId() +
94                         ')'
95                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
96                 logDebug('Entered ' + method, isDebugLogEnabled)
97
98                 try {
99                         def vnfId = execution.getVariable('UAAIVfMod_vnfId')
100                         def vfModuleId = execution.getVariable('UAAIVfMod_vfModuleId')
101
102                         // Construct endpoint
103                         AaiUtil aaiUriUtil = new AaiUtil(this)
104                         def aai_uri = aaiUriUtil.getNetworkGenericVnfUri(execution)
105                         logDebug('AAI URI is: ' + aai_uri, isDebugLogEnabled)
106                         String endPoint = execution.getVariable('URN_aai_endpoint') + aai_uri + '/' + UriUtils.encode(vnfId, "UTF-8") + '/vf-modules/vf-module/' + UriUtils.encode(vfModuleId, "UTF-8")
107
108                         try {
109                                 logDebug('sending GET to AAI endpoint \'' + endPoint + '\'', isDebugLogEnabled)
110                                 utils.logAudit("UpdateAAIVfModule sending GET to AAI endpoint: " + endPoint)
111
112                                 APIResponse response = aaiUriUtil.executeAAIGetCall(execution, endPoint)
113                                 def responseData = response.getResponseBodyAsString()
114                                 execution.setVariable('UAAIVfMod_getVfModuleResponseCode', response.getStatusCode())
115                                 execution.setVariable('UAAIVfMod_getVfModuleResponse', responseData)
116                                 logDebug('Response code:' + response.getStatusCode(), isDebugLogEnabled)
117                                 logDebug('Response:' + System.lineSeparator() + responseData, isDebugLogEnabled)
118                                 utils.logAudit("UpdateAAIVfModule response data: " + responseData)
119                         } catch (Exception ex) {
120                                 ex.printStackTrace()
121                                 logDebug('Exception occurred while executing AAI GET:' + ex.getMessage(),isDebugLogEnabled)
122                                 execution.setVariable('UAAIVfMod_getVfModuleResponseCode', 500)
123                                 execution.setVariable('UAAIVfMod_getVfModuleResponse', 'AAI GET Failed:' + ex.getMessage())
124                         }
125                         logDebug('Exited ' + method, isDebugLogEnabled)
126                 } catch (BpmnError e) {
127                         throw e;
128                 } catch (Exception e) {
129                         logError('Caught exception in ' + method, e)
130                         createWorkflowException(execution, 1002, 'Error in getVfModule(): ' + e.getMessage())
131                 }
132         }
133
134         /**
135          * Construct and send a PUT request to AAI to update the VF Module.
136          *
137          * @param execution The flow's execution instance.
138          */
139         public void updateVfModule(Execution execution) {
140                 def method = getClass().getSimpleName() + '.updateVfModule(' +
141                         'execution=' + execution.getId() +
142                         ')'
143                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
144                 logDebug('Entered ' + method, isDebugLogEnabled)
145
146                 try {
147                         def vnfId = execution.getVariable('UAAIVfMod_vnfId')
148                         def vfModuleId = execution.getVariable('UAAIVfMod_vfModuleId')
149                         def vfModule = execution.getVariable('UAAIVfMod_getVfModuleResponse')
150                         def origRequest = execution.getVariable('UpdateAAIVfModuleRequest')
151                         def Node vfModuleNode = xmlParser.parseText(vfModule)
152                         
153                         utils.logAudit("UpdateAAIVfModule request: " + origRequest)
154                         // Confirm resource-version is in retrieved VF Module
155                         if (utils.getChildNode(vfModuleNode, 'resource-version') == null) {
156                                 def msg = 'Can\'t update VF Module ' + vfModuleId + ' since \'resource-version\' is missing'
157                                 logError(msg)
158                                 throw new Exception(msg)
159                         }
160                         
161                         // TEMPORARY!!! Disable Volume Group Check
162                         // Check volume-group-id conditions
163                         //def checkVgiResult = checkVolumeGroupId(origRequest, vfModuleNode, isDebugLogEnabled)
164                         //if (checkVgiResult != null) {
165                         //      def msg = 'Can\'t update VF Module ' + vfModuleId + ': ' + checkVgiResult
166                         //      logError(msg)
167                         //      throw new Exception(msg)
168                         //}
169                         
170                         // Handle persona-model-id/persona-model-version
171                         def boolean doPersonaModelVersion = true
172                         def String newPersonaModelId = utils.getNodeText1(origRequest, 'persona-model-id')
173                         def String newPersonaModelVersion = utils.getNodeText1(origRequest, 'persona-model-version')
174                         if ((newPersonaModelId == null) || (newPersonaModelVersion == null)) {
175                                 doPersonaModelVersion = false
176                         } else {
177                                 // Confirm "new" persona-model-id is same as "current" persona-model-id
178                                 def String currPersonaModelId = utils.getChildNodeText(vfModuleNode, 'persona-model-id')
179                                 if (currPersonaModelId == null) {
180                                         currPersonaModelId = ''
181                                 }
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'
184                                         logError(msg)
185                                         throw new Exception(msg)
186                                 }
187                         }
188                         
189                         // Construct payload
190                         updateVfModuleNode(origRequest, vfModuleNode, 'orchestration-status')
191                         updateVfModuleNode(origRequest, vfModuleNode, 'heat-stack-id')
192                         if (doPersonaModelVersion) {
193                                 updateVfModuleNode(origRequest, vfModuleNode, 'persona-model-version')
194                         }
195                         updateVfModuleNode(origRequest, vfModuleNode, 'contrail-service-instance-fqdn')
196                         def payload = utils.nodeToString(vfModuleNode)
197
198                         // Construct endpoint
199                         AaiUtil aaiUriUtil = new AaiUtil(this)
200                         def aai_uri = aaiUriUtil.getNetworkGenericVnfUri(execution)
201                         logDebug('AAI URI is: ' + aai_uri, isDebugLogEnabled)
202                         String endPoint = execution.getVariable('URN_aai_endpoint') + aai_uri + '/' + UriUtils.encode(vnfId, "UTF-8") + '/vf-modules/vf-module/' + UriUtils.encode(vfModuleId, "UTF-8")
203
204                         try {
205                                 logDebug('sending PUT to AAI endpoint \'' + endPoint + '\'' + 'with payload \n' + payload, isDebugLogEnabled)
206                                 utils.logAudit("Sending PUT to AAI endpoint: " + endPoint)
207                                 
208                                 APIResponse response = aaiUriUtil.executeAAIPutCall(execution, endPoint, payload)
209                                 def responseData = response.getResponseBodyAsString()
210                                 execution.setVariable('UAAIVfMod_updateVfModuleResponseCode', response.getStatusCode())
211                                 execution.setVariable('UAAIVfMod_updateVfModuleResponse', responseData)
212                                 utils.logAudit("UpdateAAIVfModule Response data: " + responseData)
213                                 logDebug('Response code:' + response.getStatusCode(), isDebugLogEnabled)
214                                 logDebug('Response:' + System.lineSeparator() + responseData, isDebugLogEnabled)
215                         } catch (Exception ex) {
216                                 ex.printStackTrace()
217                                 logDebug('Exception occurred while executing AAI PUT:' + ex.getMessage(),isDebugLogEnabled)
218                                 execution.setVariable('UAAIVfMod_updateVfModuleResponseCode', 500)
219                                 execution.setVariable('UAAIVfMod_updateVfModuleResponse', 'AAI PUT Failed:' + ex.getMessage())
220                         }
221                         logDebug('Exited ' + method, isDebugLogEnabled)
222                 } catch (BpmnError e) {
223                         throw e;
224                 } catch (Exception e) {
225                         logError('Caught exception in ' + method, e)
226                         createWorkflowException(execution, 1002, 'Error in updateVfModule(): ' + e.getMessage())
227                 }
228         }
229
230         /**
231          * Insert a new Node, replace the value of an existing Node, or delete an existing Node in the current
232          * VF Module Node, as necessary.
233          *
234          * If the Node with the same name already exists in current VF Module, but is not being updated, then do
235          * nothing. If the element is being updated and it already exists in the current VF Module, then check
236          * the value specified in the original request. If the value is 'DELETE', remove that Node from the
237          * current VF Module.  Otherwise, change the value to the specified new value. If the element is
238          * being updated but doesn't exist in the current VF Module, and the new value is not 'DELETE', then
239          * create an appropriate new node and add it to the VF Module.
240          *
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.
244          */
245         private void updateVfModuleNode(String origRequest, Node vfModuleNode, String elementName) {
246
247                 if (!utils.nodeExists(origRequest, elementName)) {
248                         return
249                 }
250                 def elementValue = utils.getNodeText(origRequest, elementName)
251
252                 def Node childNode = utils.getChildNode(vfModuleNode, elementName)
253                 if (childNode == null) {
254                         if (elementValue.equals('DELETE')) {
255                                 // Element doesn't exist but is being deleted, so do nothing
256                                 return
257                         }
258                         // Node doesn't exist, create a new Node as a child
259                         new Node(vfModuleNode, elementName, elementValue)
260                 } else {
261                         if (elementValue.equals('DELETE')) {
262                                 // Node exists, but should be deleted
263                                 vfModuleNode.remove(childNode)
264                         } else {
265                                 // Node already exists, just give it a new value
266                                 childNode.setValue(elementValue)
267                         }
268                 }
269         }
270         
271         /**
272          * Check the Volume Group ID from the incoming update request against the Volume Group ID from the
273          * given VF Module.  If they are equal or if they are both 'null', then that is acceptable and 'null'
274          * is returned.  Otherwise a message describing how the values are unacceptable/incompatible is returned.
275          * 
276          * @param origRequest Incoming update request with VF Module elements to be updated.
277          * @param vfModuleNode VF Module (as a Node) retrieved from AAI.
278          * @param isDebugLogEnabled Is DEBUG log enabled?
279          * @return 'null' if the Volume Group IDs are acceptable. Otherwise return a message describing how the
280          * values are unacceptable/incompatible.
281          */
282         private String checkVolumeGroupId(String origRequest, Node vfModuleNode, String isDebugLogEnabled) {
283                 def requestVolumeGroupId = utils.getNodeText1(origRequest, 'volume-group-id')
284                 def currVolumeGroupId = getCurrVolumeGroupId(vfModuleNode)
285                 
286                 logDebug('Check volume-group-id: volume-group-id in original request is \'' + requestVolumeGroupId +
287                         '\', volume-group-id from VF Module is \'' + currVolumeGroupId + '\'', isDebugLogEnabled)
288                 
289                 def result = null
290                 
291                 if (requestVolumeGroupId == null) {
292                         if (currVolumeGroupId == null) {
293                                 // This is OK
294                         } else {
295                                 result = 'Cannot detach a volume group from an existing VF Module'
296                         }
297                 } else {
298                         if (currVolumeGroupId == null) {
299                                 result = 'Cannot add a volume gruop to an existing VF Module'
300                         } else {
301                                 if (!requestVolumeGroupId.equals(currVolumeGroupId)) {
302                                         result = 'Cannot change the volume group on an existing VF Module'
303                                 }
304                         }
305                 }
306                 
307                 return result
308         }
309         
310         /**
311          * Find and return the value of the Volume Group ID for the specified VF Module.  If
312          * the value of the Volume Group ID cannot be found for any reason, 'null' is returned.
313          * 
314          * @param vfModuleNode VF Module (as a Node) retrieved from AAI.
315          * @return the value of the Volume Group ID for the specified VF Module.  If the
316          * value of the Volume Group ID cannot be found for any reason, 'null' is returned.
317          */
318         private String getCurrVolumeGroupId(Node vfModuleNode) {
319                 def Node relationshipList = utils.getChildNode(vfModuleNode, 'relationship-list')
320                 if (relationshipList == null) {
321                         return null
322                 }
323                 def NodeList relationships = utils.getIdenticalChildren(relationshipList, 'relationship')
324                 for (Node relationshipNode in relationships) {
325                         def String relatedTo = utils.getChildNodeText(relationshipNode, 'related-to')
326                         if ((relatedTo != null) && relatedTo.equals('volume-group')) {
327                                 def NodeList relationshipDataList = utils.getIdenticalChildren(relationshipNode, 'relationship-data')
328                                 for (Node relationshipDataNode in relationshipDataList) {
329                                         def String relationshipKey = utils.getChildNodeText(relationshipDataNode, 'relationship-key')
330                                         if ((relationshipKey != null) && relationshipKey.equals('volume-group.volume-group-id')) {
331                                                 return utils.getChildNodeText(relationshipDataNode, 'relationship-value')
332                                         }
333                                 }
334                         }
335                 }
336                 return null
337         }
338
339         /**
340          * Generates a WorkflowException if the AAI query returns a response code other than 200.
341          *
342          * @param execution The flow's execution instance.
343          */
344         public void handleAAIQueryFailure(Execution execution) {
345                 def method = getClass().getSimpleName() + '.handleAAIQueryFailure(' +
346                         'execution=' + execution.getId() +
347                         ')'
348                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
349                 logDebug('Entered ' + method, isDebugLogEnabled)
350
351                 logError('Error occurred attempting to query AAI, Response Code ' +
352                         execution.getVariable('UAAIVfMod_getVfModuleResponseCode') + ', Error Response ' +
353                         execution.getVariable('UAAIVfMod_getVfModuleResponse'))
354                 String processKey = getProcessKey(execution);
355                 WorkflowException exception = new WorkflowException(processKey, 5000,
356                         execution.getVariable('UAAIVfMod_getVfModuleResponse'))
357                 execution.setVariable('WorkflowException', exception)
358                 utils.logAudit("UpdateAAIVfModule query failure: " + exception.getErrorMessage())
359                 logDebug('Exited ' + method, isDebugLogEnabled)
360         }
361
362         /**
363          * Generates a WorkflowException if updating a VF Module in AAI returns a response code other than 200.
364          *
365          * @param execution The flow's execution instance.
366          */
367         public void handleUpdateVfModuleFailure(Execution execution) {
368                 def method = getClass().getSimpleName() + '.handleUpdateVfModuleFailure(' +
369                         'execution=' + execution.getId() +
370                         ')'
371                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
372                 logDebug('Entered ' + method, isDebugLogEnabled)
373
374                 logError('Error occurred attempting to update VF Module in AAI, Response Code ' +
375                         execution.getVariable('UAAIVfMod_updateVfModuleResponseCode') + ', Error Response ' +
376                         execution.getVariable('UAAIVfMod_updateVfModuleResponse'))
377                 String processKey = getProcessKey(execution);
378                 WorkflowException exception = new WorkflowException(processKey, 5000,
379                         execution.getVariable('UAAIVfMod_updateVfModuleResponse'))
380                 execution.setVariable('WorkflowException', exception)
381
382                 utils.logAudit("UpdateAAIVfModule failure: " + exception.getErrorMessage())
383                 logDebug('Exited ' + method, isDebugLogEnabled)
384         }
385 }