Initial OpenECOMP MSO commit
[so.git] / bpmn / MSOGammaBPMN / src / main / groovy / com / att / bpm / scripts / CreateAAIVfModuleVolumeGroup.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 com.att.bpm.scripts
22
23 import groovy.util.Node
24 import groovy.util.XmlParser;
25 import groovy.xml.QName
26
27 import java.io.Serializable;
28
29 import org.camunda.bpm.engine.delegate.BpmnError
30 import org.camunda.bpm.engine.runtime.Execution
31
32 import org.openecomp.mso.rest.APIResponse
33 import org.openecomp.mso.rest.RESTClient
34 import org.openecomp.mso.rest.RESTConfig
35 import org.openecomp.mso.bpmn.core.RollbackData
36 import org.openecomp.mso.bpmn.core.WorkflowException
37
38
39 public class CreateAAIVfModuleVolumeGroup extends AbstractServiceTaskProcessor {
40
41         private XmlParser xmlParser = new XmlParser()
42
43         /**
44          * Initialize the flow's variables.
45          *
46          * @param execution The flow's execution instance.
47          */
48         public void initProcessVariables(Execution execution) {
49                 execution.setVariable('prefix', 'CAAIVfModVG_')
50                 execution.setVariable('CAAIVfModVG_vnfId', null)
51                 execution.setVariable('CAAIVfModVG_vfModuleId', null)
52                 execution.setVariable('CAAIVfModVG_aicCloudRegion', null)
53                 execution.setVariable('CAAIVfModVG_volumeGroupId', null)
54                 execution.setVariable('CAAIVfModVG_getVfModuleResponseCode' ,null)
55                 execution.setVariable('CAAIVfModVG_getVfModuleResponse', '')
56                 execution.setVariable('CAAIVfModVG_updateVfModuleResponseCode', null)
57                 execution.setVariable('CAAIVfModVG_updateVfModuleResponse', '')
58         }
59
60         /**
61          * Check for missing elements in the received request.
62          *
63          * @param execution The flow's execution instance.
64          */
65         public void preProcessRequest(Execution execution) {
66                 def method = getClass().getSimpleName() + '.preProcessRequest(' +
67                         'execution=' + execution.getId() +
68                         ')'
69                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
70                 logDebug('Entered ' + method, isDebugLogEnabled)
71
72                 try {
73                         def xml = execution.getVariable('CreateAAIVfModuleVolumeGroupRequest')
74                         logDebug('Received request xml:\n' + xml, isDebugLogEnabled)
75                         initProcessVariables(execution)
76
77                         def vnfId = getRequiredNodeText(execution, xml,'vnf-id')
78                         execution.setVariable('CAAIVfModVG_vnfId', vnfId)
79
80                         def vfModuleId = getRequiredNodeText(execution, xml,'vf-module-id')
81                         execution.setVariable('CAAIVfModVG_vfModuleId', vfModuleId)
82                         
83                         def aicCloudRegion = getRequiredNodeText(execution, xml,'aic-cloud-region')
84                         execution.setVariable('CAAIVfModVG_aicCloudRegion', aicCloudRegion)
85                         
86                         def volumeGroupId = getRequiredNodeText(execution, xml,'volume-group-id')
87                         execution.setVariable('CAAIVfModVG_volumeGroupId', volumeGroupId)
88
89                         logDebug('Exited ' + method, isDebugLogEnabled)
90                 } catch (BpmnError e) {
91                         throw e;
92                 } catch (Exception e) {
93                         logError('Caught exception in ' + method, e)
94                         createWorkflowException(execution, 1002, 'Error in preProcessRequest(): ' + e.getMessage())
95                 }
96         }
97
98         /**
99          * Using the received vnfId and vfModuleId, query AAI to get the corresponding VF Module.
100          * A 200 response is expected with the VF Module in the response body.
101          *
102          * @param execution The flow's execution instance.
103          */
104         public void getVfModule(Execution execution) {
105                 def method = getClass().getSimpleName() + '.getVfModule(' +
106                         'execution=' + execution.getId() +
107                         ')'
108                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
109                 logDebug('Entered ' + method, isDebugLogEnabled)
110
111                 try {
112                         def vnfId = execution.getVariable('CAAIVfModVG_vnfId')
113                         def vfModuleId = execution.getVariable('CAAIVfModVG_vfModuleId')
114
115                         // Construct endpoint
116                         AaiUtil aaiUtil = new AaiUtil(this)
117                         def aai_uri = aaiUtil.getNetworkGenericVnfUri(execution)
118                         logDebug('AAI URI is: ' + aai_uri, isDebugLogEnabled)
119                         String endPoint = execution.getVariable('URN_aai_endpoint') + aai_uri + '/' + URLEncoder.encode(vnfId, "UTF-8") + '/vf-modules/vf-module/' + URLEncoder.encode(vfModuleId, "UTF-8")
120
121                         try {
122                                 logDebug('sending GET to AAI endpoint \'' + endPoint + '\'', isDebugLogEnabled)
123                                 APIResponse response = aaiUtil.executeAAIGetCall(execution, endPoint)
124                                 def responseData = response.getResponseBodyAsString()
125                                 execution.setVariable('CAAIVfModVG_getVfModuleResponseCode', response.getStatusCode())
126                                 execution.setVariable('CAAIVfModVG_getVfModuleResponse', responseData)
127                                 logDebug('Response code:' + response.getStatusCode(), isDebugLogEnabled)
128                                 logDebug('Response:' + System.lineSeparator() + responseData, isDebugLogEnabled)
129                         } catch (Exception ex) {
130                                 ex.printStackTrace()
131                                 logDebug('Exception occurred while executing AAI GET:' + ex.getMessage(),isDebugLogEnabled)
132                                 execution.setVariable('CAAIVfModVG_getVfModuleResponseCode', 500)
133                                 execution.setVariable('CAAIVfModVG_getVfModuleResponse', 'AAI GET Failed:' + ex.getMessage())
134                         }
135                         logDebug('Exited ' + method, isDebugLogEnabled)
136                 } catch (BpmnError e) {
137                         throw e;
138                 } catch (Exception e) {
139                         logError('Caught exception in ' + method, e)
140                         createWorkflowException(execution, 1002, 'Error in getVfModule(): ' + e.getMessage())
141                 }
142         }
143
144         /**
145          * Construct and send a PUT request to AAI to update the VF Module with the
146          * created Volume Group relationship.
147          *
148          * @param execution The flow's execution instance.
149          */
150         public void updateVfModule(Execution execution) {
151                 def method = getClass().getSimpleName() + '.updateVfModule(' +
152                         'execution=' + execution.getId() +
153                         ')'
154                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
155                 logDebug('Entered ' + method, isDebugLogEnabled)
156
157                 try {
158                         def vnfId = execution.getVariable('CAAIVfModVG_vnfId')
159                         def vfModuleId = execution.getVariable('CAAIVfModVG_vfModuleId')
160                         def vfModule = execution.getVariable('CAAIVfModVG_getVfModuleResponse')
161                         def origRequest = execution.getVariable('CreateAAIVfModuleVolumeGroupRequest')
162                         def Node vfModuleNode = xmlParser.parseText(vfModule)
163                         
164                         // Confirm resource-version is in retrieved VF Module
165                         if (utils.getChildNode(vfModuleNode, 'resource-version') == null) {
166                                 def msg = 'Can\'t update VF Module ' + vfModuleId + ' since \'resource-version\' is missing'
167                                 logError(msg)
168                                 throw new Exception(msg)
169                         }
170                                                 
171                         // Construct payload by creating a Volume Group relationhip and inserting it into the VF Module
172                         def aicCloudRegion = execution.getVariable('CAAIVfModVG_aicCloudRegion')
173                         def volumeGroupId = execution.getVariable('CAAIVfModVG_volumeGroupId')
174                         def Node vgRelationshipNode = createVolumeGroupRelationshipNode(aicCloudRegion, volumeGroupId)
175                         insertVolumeGroupRelationshipNode(vfModuleNode, vgRelationshipNode)
176                         def payload = utils.nodeToString(vfModuleNode)
177
178                         // Construct endpoint
179                         AaiUtil aaiUtil = new AaiUtil(this)
180                         def aai_uri = aaiUtil.getNetworkGenericVnfUri(execution)
181                         logDebug('AAI URI is: ' + aai_uri, isDebugLogEnabled)
182                         String endPoint = execution.getVariable('URN_aai_endpoint') + aai_uri + '/' + URLEncoder.encode(vnfId, "UTF-8") + '/vf-modules/vf-module/' + URLEncoder.encode(vfModuleId, "UTF-8")
183
184                         try {
185                                 logDebug('sending PUT to AAI endpoint \'' + endPoint + '\'' + 'with payload \n' + payload, isDebugLogEnabled)
186                                 APIResponse response = aaiUtil.executeAAIPutCall(execution, endPoint, payload)
187                                 def responseData = response.getResponseBodyAsString()
188                                 execution.setVariable('CAAIVfModVG_updateVfModuleResponseCode', response.getStatusCode())
189                                 execution.setVariable('CAAIVfModVG_updateVfModuleResponse', responseData)
190                                 logDebug('Response code:' + response.getStatusCode(), isDebugLogEnabled)
191                                 logDebug('Response:' + System.lineSeparator() + responseData, isDebugLogEnabled)
192                         } catch (Exception ex) {
193                                 ex.printStackTrace()
194                                 logDebug('Exception occurred while executing AAI PUT:' + ex.getMessage(),isDebugLogEnabled)
195                                 execution.setVariable('CAAIVfModVG_updateVfModuleResponseCode', 500)
196                                 execution.setVariable('CAAIVfModVG_updateVfModuleResponse', 'AAI PUT Failed:' + ex.getMessage())
197                         }
198                         logDebug('Exited ' + method, isDebugLogEnabled)
199                 } catch (BpmnError e) {
200                         throw e;
201                 } catch (Exception e) {
202                         logError('Caught exception in ' + method, e)
203                         createWorkflowException(execution, 1002, 'Error in updateVfModule(): ' + e.getMessage())
204                 }
205         }
206
207         /**
208          * Construct a Volume Group relationship Node with the given AIC Cloud Region and
209          * Volume Group ID for insertion into a VF Module.
210          * 
211          * @param aicCloudRegion Cloud Region ID to use in the Volume Group relationship
212          * @param volumeGroupId Volume Group ID to use in the Volume Group relationship
213          * @return a Node representing the new Volume Group relationship
214          */
215         private Node createVolumeGroupRelationshipNode(String aicCloudRegion, String volumeGroupId) {
216                 
217                 def Node relatedTo = new Node(null, 'related-to', 'volume-group')
218                 
219                 def Node relationshipKeyCO = new Node(null, 'relationship-key', 'cloud-region.cloud-owner')
220                 def Node relationshipValueCO = new Node(null, 'relationship-value', 'att-aic')
221                 def Node relationshipDataCO = new Node(null, 'relationship-data')
222                 relationshipDataCO.append(relationshipKeyCO)
223                 relationshipDataCO.append(relationshipValueCO)
224                 
225                 def Node relationshipKeyCRI = new Node(null, 'relationship-key', 'cloud-region.cloud-region-id')
226                 def Node relationshipValueCRI = new Node(null, 'relationship-value', aicCloudRegion)
227                 def Node relationshipDataCRI = new Node(null, 'relationship-data')
228                 relationshipDataCRI.append(relationshipKeyCRI)
229                 relationshipDataCRI.append(relationshipValueCRI)
230
231                 def Node relationshipKeyVGI = new Node(null, 'relationship-key', 'volume-group.volume-group-id')
232                 def Node relationshipValueVGI = new Node(null, 'relationship-value', volumeGroupId)
233                 def Node relationshipDataVGI = new Node(null, 'relationship-data')
234                 relationshipDataVGI.append(relationshipKeyVGI)
235                 relationshipDataVGI.append(relationshipValueVGI)
236                 
237                 def Node volumeGroupRelationship = new Node(null, 'relationship')
238                 volumeGroupRelationship.append(relatedTo)
239                 volumeGroupRelationship.append(relationshipDataCO)
240                 volumeGroupRelationship.append(relationshipDataCRI)
241                 volumeGroupRelationship.append(relationshipDataVGI)
242                 
243                 return volumeGroupRelationship;
244         }
245         
246         /**
247          * Insert the given Volume Group relationship Node into the given VF Module.
248          * If the VF Module does NOT contain a relationship list:
249          *      - Create a relationship list containing the Volume Group relationship and insert it into the VF Module
250          * If the VF Module contains a relationship list but not a Volume Group relationship:
251          *      - Insert the the Volume Group relationship into the relationship lsit
252          * If the VF Module contains a relationship list and has a Volume Group relationship:
253          *      - Replace the existing Volume Group relationship with the new one
254          * @param vfModuleNode
255          * @param volumeGroupRelationshipNode
256          */
257         private void insertVolumeGroupRelationshipNode(Node vfModuleNode, Node volumeGroupRelationshipNode) {
258                 def Node relationshipList = utils.getChildNode(vfModuleNode, 'relationship-list')
259                 if (relationshipList == null) {
260                         relationshipList = new Node(null, 'relationship-list')
261                         relationshipList.append(volumeGroupRelationshipNode)
262                         vfModuleNode.append(relationshipList)
263                 } else {
264                         def Node currVolumeGroupRelationshipNode = getCurrVolumeGroupRelationshipNode(relationshipList)
265                         if (currVolumeGroupRelationshipNode == null) {
266                                 relationshipList.append(volumeGroupRelationshipNode)
267                         } else {
268                                 currVolumeGroupRelationshipNode.replaceNode(volumeGroupRelationshipNode)
269                         }
270                 }
271         }
272                 
273         /**
274          * Find and return the value of the Volume Group ID for the specified VF Module.  If
275          * the value of the Volume Group ID cannot be found for any reason, 'null' is returned.
276          * 
277          * @param vfModuleNode VF Module (as a Node) retrieved from AAI.
278          * @return the value of the Volume Group ID for the specified VF Module.  If the
279          * value of the Volume Group ID cannot be found for any reason, 'null' is returned.
280          */
281         private Node getCurrVolumeGroupRelationshipNode(Node relationshipList) {
282                 def Node currVolumeGroupRelationshipNode = null
283                 def NodeList relationships = utils.getIdenticalChildren(relationshipList, 'relationship')
284                 for (Node relationshipNode in relationships) {
285                         def String relatedTo = utils.getChildNodeText(relationshipNode, 'related-to')
286                         if ((relatedTo != null) && relatedTo.equals('volume-group')) {
287                                 currVolumeGroupRelationshipNode = relationshipNode
288                         }
289                 }
290                 return currVolumeGroupRelationshipNode
291         }
292
293         /**
294          * Generates a WorkflowException if the AAI query returns a response code other than 200.
295          *
296          * @param execution The flow's execution instance.
297          */
298         public void handleAAIQueryFailure(Execution execution) {
299                 def method = getClass().getSimpleName() + '.handleAAIQueryFailure(' +
300                         'execution=' + execution.getId() +
301                         ')'
302                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
303                 logDebug('Entered ' + method, isDebugLogEnabled)
304
305                 logError('Error occurred attempting to query AAI, Response Code ' +
306                         execution.getVariable('CAAIVfModVG_getVfModuleResponseCode') + ', Error Response ' +
307                         execution.getVariable('CAAIVfModVG_getVfModuleResponse'))
308                 ExceptionUtil exceptionUtil = new ExceptionUtil()
309                 exceptionUtil.buildWorkflowException(execution, 5000, execution.getVariable('CAAIVfModVG_getVfModuleResponse'))
310
311                 logDebug('Exited ' + method, isDebugLogEnabled)
312         }
313
314         /**
315          * Generates a WorkflowException if updating a VF Module in AAI returns a response code other than 200.
316          *
317          * @param execution The flow's execution instance.
318          */
319         public void handleUpdateVfModuleFailure(Execution execution) {
320                 def method = getClass().getSimpleName() + '.handleUpdateVfModuleFailure(' +
321                         'execution=' + execution.getId() +
322                         ')'
323                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
324                 logDebug('Entered ' + method, isDebugLogEnabled)
325
326                 logError('Error occurred attempting to update VF Module in AAI, Response Code ' +
327                         execution.getVariable('CAAIVfModVG_updateVfModuleResponseCode') + ', Error Response ' +
328                         execution.getVariable('CAAIVfModVG_updateVfModuleResponse'))
329                 ExceptionUtil exceptionUtil = new ExceptionUtil()
330                 exceptionUtil.buildWorkflowException(execution, 5000, execution.getVariable('CAAIVfModVG_updateVfModuleResponse'))
331
332                 logDebug('Exited ' + method, isDebugLogEnabled)
333         }
334 }