c4321220fdea7eb23f0102b63828ba0158bf46ed
[so.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  # Copyright (c) 2019, CMCC Technologies Co., Ltd.
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 package org.onap.so.bpmn.infrastructure.scripts
21
22 import static org.apache.commons.lang3.StringUtils.isBlank
23 import javax.ws.rs.NotFoundException
24 import javax.ws.rs.core.Response
25 import org.camunda.bpm.engine.delegate.BpmnError
26 import org.camunda.bpm.engine.delegate.DelegateExecution
27 import org.onap.aai.domain.yang.AllottedResource
28 import org.onap.aai.domain.yang.AllottedResources
29 import org.onap.aai.domain.yang.Relationship
30 import org.onap.aai.domain.yang.ServiceInstance
31 import org.onap.aai.domain.yang.ServiceProfile
32 import org.onap.aai.domain.yang.ServiceProfiles
33 import org.onap.aaiclient.client.aai.AAIObjectName
34 import org.onap.aaiclient.client.aai.entities.AAIResultWrapper
35 import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory
36 import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder
37 import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder.Types
38 import org.onap.logging.filter.base.ONAPComponents
39 import org.onap.so.bpmn.common.scripts.AbstractServiceTaskProcessor
40 import org.onap.so.bpmn.common.scripts.ExceptionUtil
41 import org.onap.so.bpmn.common.scripts.OofUtils
42 import org.onap.so.bpmn.core.UrnPropertiesReader
43 import org.onap.so.client.HttpClient
44 import org.onap.so.client.HttpClientFactory
45 import org.slf4j.Logger
46 import org.slf4j.LoggerFactory
47
48 /**
49  * This groovy class supports the <class>DoDeleteSliceService.bpmn</class> process.
50  *
51  * Inputs:
52  * @param - msoRequestId
53  * @param - globalSubscriberId - O
54  * @param - subscriptionServiceType - O
55  * @param - serviceInstanceId
56  *
57  */
58 class DoDeleteSliceService extends AbstractServiceTaskProcessor {
59     private final String PREFIX ="DoDeleteSliceService"
60     ExceptionUtil exceptionUtil = new ExceptionUtil()
61     OofUtils oofUtils = new OofUtils()
62     private static final Logger LOGGER = LoggerFactory.getLogger( DoDeleteSliceService.class)
63
64     @Override
65     void preProcessRequest(DelegateExecution execution) {
66         LOGGER.debug(" *****${PREFIX} preProcessRequest *****")
67         String msg = ""
68
69         try {
70             //String requestId = execution.getVariable("msoRequestId")
71             execution.setVariable("prefix",PREFIX)
72
73             //Inputs
74             //requestDetails.subscriberInfo. for AAI GET & PUT
75              execution.getVariable("globalSubscriberId") ?: execution.setVariable("globalSubscriberId", "")
76
77             //requestDetails.requestParameters. for AAI PUT
78             execution.getVariable("serviceType") ?: execution.setVariable("serviceType", "")
79
80             //Generated in parent for AAI PUT
81             String serviceInstanceId = execution.getVariable("serviceInstanceId")
82             if (isBlank(serviceInstanceId)){
83                 msg = "Input serviceInstanceId is null"
84                 LOGGER.info(msg)
85                 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
86             }
87         } catch (BpmnError e) {
88             throw e
89         } catch (Exception ex){
90             msg = "Exception in preProcessRequest " + ex.getMessage()
91             LOGGER.error(msg)
92             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
93         }
94         LOGGER.debug("*****${PREFIX} Exit preProcessRequest *****")
95     }
96
97     /**
98      * query E2ESliceService from AAI
99      * save snssai
100      * @param execution
101      */
102     void queryE2ESliceSeriveFromAAI(DelegateExecution execution)
103     {
104         LOGGER.trace(" *****${PREFIX} Start queryE2ESliceSeriveFromAAI *****")
105         String serviceInstanceId = execution.getVariable("serviceInstanceId")
106         try
107         {
108         String errorMsg = "query e2e slice service from aai failed"
109         AAIResultWrapper wrapper = queryAAI(execution, Types.SERVICE_INSTANCE, serviceInstanceId, errorMsg)
110         Optional<ServiceInstance> si =wrapper.asBean(ServiceInstance.class)
111         if(si.isPresent())
112         {
113             String snssai = si.get()?.getEnvironmentContext()
114             ServiceProfiles serviceProfiles = si.get()?.getServiceProfiles()
115             ServiceProfile serviceProfile = serviceProfiles.getServiceProfile().get(0)
116             String serviceProfileId = serviceProfile ? serviceProfile.getProfileId() : ""
117             execution.setVariable("snssai", snssai ?: "")
118             execution.setVariable("serviceProfileId",serviceProfileId)
119             List<ServiceInstance> sliceProfileList = []
120             List<Relationship> relationshipList = si.get().getRelationshipList().getRelationship()
121             for (Relationship relationship : relationshipList) {
122                 String relatedTo = relationship.getRelatedTo()
123                 if (relatedTo.toLowerCase() == "service-instance") {
124                     String relatioshipurl = relationship.getRelatedLink()
125                     String instanceId = relatioshipurl.substring(relatioshipurl.lastIndexOf("/") + 1, relatioshipurl.length())
126                     AAIResultWrapper wrapper1 = queryAAI(execution, Types.SERVICE_INSTANCE, instanceId, errorMsg)
127                     Optional<ServiceInstance> serviceInstance = wrapper1.asBean(ServiceInstance.class)
128                     if (serviceInstance.isPresent()) {
129                         ServiceInstance instance = serviceInstance.get()
130                         if ("slice-profile-instance".equalsIgnoreCase(instance.getServiceRole())) {
131                             sliceProfileList.add(instance)
132                         }
133                     }
134                 }
135             }
136             execution.setVariable("sliceProfileList",sliceProfileList)
137             LOGGER.info("serviceInstanceId: ${serviceInstanceId}, snssai: ${snssai}, sliceProfileList: ${sliceProfileList}")
138         }
139         LOGGER.trace(" *****${PREFIX} Exit queryE2ESliceSeriveFromAAI *****")
140         }
141         catch (any)
142         {
143             String msg = "query E2E slice service from aai failed! cause-"+any.getCause()
144             LOGGER.error(any.printStackTrace())
145             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg);
146         }
147     }
148
149     /**
150      * get allotted resource from AAI
151      * save nsi id
152      * @param execution
153      */
154     void getAllottedResFromAAI(DelegateExecution execution)
155     {
156         LOGGER.trace(" *****${PREFIX} Start getAllottedResFromAAI *****")
157         String serviceInstanceId = execution.getVariable("serviceInstanceId")
158         try
159         {
160             String errorMsg = "query allotted resource from aai failed."
161             AAIResultWrapper wrapper = queryAAI(execution, Types.ALLOTTED_RESOURCES, serviceInstanceId, errorMsg)
162             Optional<AllottedResources> ars = wrapper?.asBean(AllottedResources.class)
163             if(ars.isPresent() && ars.get().getAllottedResource())
164             {
165                 List<AllottedResource> allottedResourceList = ars.get().getAllottedResource()
166                 AllottedResource ar = allottedResourceList.first()
167                 String relatedLink = ar?.getRelationshipList()?.getRelationship()?.first()?.getRelatedLink()
168                 String nsiId = relatedLink ? relatedLink.substring(relatedLink.lastIndexOf("/") + 1,relatedLink.length()) : ""
169                 execution.setVariable("nsiId", nsiId)
170                 LOGGER.info("serviceInstanceId: ${serviceInstanceId}, nsiId:${nsiId}")
171             }
172         }
173         catch(BpmnError e){
174             throw e
175         }
176         catch (Exception ex){
177             String msg = "Exception in getAllottedResFromAAI " + ex.getMessage()
178             LOGGER.error(msg)
179             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
180         }
181         LOGGER.trace(" *****${PREFIX} Exit getAllottedResFromAAI *****")
182     }
183
184     /**
185      * get nsi service instance from aai
186      * save nssi id
187      * @param execution
188      */
189     void getNSIFromAAI(DelegateExecution execution)
190     {
191         LOGGER.trace(" *****${PREFIX} Start getNSIFromAAI *****")
192         String nsiId = execution.getVariable("nsiId")
193         try
194         {
195             String errorMsg = "query nsi from aai failed."
196             AAIResultWrapper wrapper = queryAAI(execution, Types.SERVICE_INSTANCE, nsiId, errorMsg)
197             Optional<ServiceInstance> si =wrapper.asBean(ServiceInstance.class)
198             List<String> nssiIdList = []
199             String msg = "nsiId:${nsiId},nssiIdList:"
200             if(si.isPresent())
201             {
202                 List<Relationship> relationshipList = si.get().getRelationshipList()?.getRelationship()
203                 for (Relationship relationship : relationshipList)
204                 {
205                     String relatedTo = relationship.getRelatedTo()
206                     if (relatedTo == "service-instance")
207                     {
208                         String relatedLink = relationship.getRelatedLink()?:""
209                         String instanceId = relatedLink ? relatedLink.substring(relatedLink.lastIndexOf("/") + 1,relatedLink.length()) : ""
210                         AAIResultWrapper wrapper1 = queryAAI(execution, Types.SERVICE_INSTANCE, instanceId, errorMsg)
211                         Optional<ServiceInstance> serviceInstance = wrapper1.asBean(ServiceInstance.class)
212                         if (serviceInstance.isPresent()) {
213                             ServiceInstance instance = serviceInstance.get()
214                             if ("nssi".equalsIgnoreCase(instance.getServiceRole())) {
215                                 nssiId = instance.getServiceInstanceId()
216                             }
217                         }
218                         nssiIdList.add(nssiId)
219                         msg+="${nssiId}, "
220                     }
221                 }
222             }
223             LOGGER.info(msg)
224             execution.setVariable("nssiIdList", nssiIdList)
225         }
226         catch(BpmnError e){
227             throw e
228         }
229         catch (Exception ex){
230             String msg = "Exception in getNSIFromAAI " + ex.getMessage()
231             LOGGER.error(msg)
232             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
233         }
234         LOGGER.trace(" *****${PREFIX} Exit getNSIFromAAI *****")
235     }
236
237     /**
238      * get nssi service from AAI
239      * prepare list
240      * @param execution
241      */
242     void getNSSIListFromAAI(DelegateExecution execution)
243     {
244         LOGGER.trace("*****${PREFIX} Start getNSSIListFromAAI *****")
245         List<String> nssiIdList = execution.getVariable("nssiIdList")
246         List<ServiceInstance> nssiInstanceList = []
247         String errorMsg = "query nssi list from aai failed"
248         for(String nssiId : nssiIdList)
249         {
250             AAIResultWrapper wrapper = queryAAI(execution, Types.SERVICE_INSTANCE, nssiId, errorMsg)
251             Optional<ServiceInstance> si =wrapper.asBean(ServiceInstance.class)
252             if(si.isPresent())
253             {
254                 nssiInstanceList.add(si.get())
255             }
256         }
257         int size = nssiInstanceList.size()
258         int proportion = size >0 ?((90/size) as int) : 90
259         execution.setVariable("nssiInstanceList", nssiInstanceList)
260         execution.setVariable("currentNSSIIndex", 0)
261         execution.setVariable("proportion", proportion)
262         String msg ="nssiInstanceList size: ${nssiInstanceList.size()}, proportion:${proportion}"
263         LOGGER.info(msg)
264         LOGGER.trace(" *****${PREFIX} Exit getNSSIListFromAAI *****")
265     }
266
267     /**
268      * get current NSSI
269      * @param execution
270      */
271     void getCurrentNSSI(DelegateExecution execution)
272     {
273         LOGGER.trace(" *****${PREFIX} Start getCurrentNSSI *****")
274         List<ServiceInstance> nssiInstanceList = execution.getVariable("nssiInstanceList")
275         List<ServiceInstance> sliceProfileList = execution.getVariable("sliceProfileList")
276         int currentIndex = execution.getVariable("currentNSSIIndex") as int
277         String profileId = ""
278         ServiceInstance nssi = nssiInstanceList?.get(currentIndex)
279         for(ServiceInstance sliceProfileInstance : sliceProfileList) {
280             if(sliceProfileInstance.getWorkloadContext().equalsIgnoreCase(nssi.getWorkloadContext()))
281             {
282                 profileId = sliceProfileInstance.getServiceInstanceId()
283             }
284         }
285         def currentNSSI = [:]
286         currentNSSI['nssiServiceInstanceId'] = nssi?.getServiceInstanceId()
287         currentNSSI['modelInvariantId'] = nssi?.getModelInvariantId()
288         currentNSSI['modelVersionId'] = nssi?.getModelVersionId()
289         currentNSSI['nssiName'] = nssi?.getServiceInstanceName()
290         currentNSSI['sST'] = nssi?.getServiceType()
291         currentNSSI['PLMNIdList'] = nssi?.getServiceInstanceLocationId()
292         currentNSSI['profileId'] =  profileId
293         currentNSSI['snssai'] = execution.getVariable("snssai") ?: ""
294         currentNSSI['nsiServiceInstanceId'] = execution.getVariable("nsiId") ?: ""
295         currentNSSI['operationId'] = execution.getVariable("operationId") ?: ""
296         currentNSSI['e2eServiceInstanceId'] = execution.getVariable("serviceInstanceId") ?: ""
297         currentNSSI['msoRequestId'] = execution.getVariable("msoRequestId") ?: ""
298         currentNSSI['globalSubscriberId'] = execution.getVariable("globalSubscriberId") ?: ""
299         currentNSSI['serviceType'] = execution.getVariable("serviceType") ?: ""
300         currentNSSI['serviceModelInfo'] = execution.getVariable("serviceModelInfo") ?: ""
301         currentNSSI['proportion'] = (execution.getVariable("proportion") as int)*(currentIndex+1)
302         execution.setVariable("currentNSSI", currentNSSI)
303         String msg = "Now we deal with nssiServiceInstanceId: ${currentNSSI['nssiServiceInstanceId']}, current Index: ${currentIndex}, current proportion:${currentNSSI['proportion']}"
304         LOGGER.info(msg)
305         LOGGER.trace(" *****${PREFIX} Exit getCurrentNSSI *****")
306     }
307
308     /**
309      * parse next nssi
310      * @param execution
311      */
312     void parseNextNSSI(DelegateExecution execution)
313     {
314         LOGGER.trace(" *****${PREFIX} Start parseNextNSSI *****")
315         if(execution.getVariable("WorkflowException") != null){
316             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, "current job failure!")
317         }
318         def currentIndex = execution.getVariable("currentNSSIIndex")
319         List<ServiceInstance> nssiInstanceList = execution.getVariable("nssiInstanceList")
320         def nextIndex = ++currentIndex
321         LOGGER.info("nextIndex: ${nextIndex}")
322         if(nextIndex >= nssiInstanceList.size()){
323             execution.setVariable("isAllNSSIFinished", "true")
324         }else{
325             execution.setVariable("isAllNSSIFinished", "false")
326             execution.setVariable("currentNSSIIndex", nextIndex)
327         }
328         LOGGER.trace(" *****${PREFIX} Exit parseNextNSSI *****")
329     }
330
331     /**
332      * query AAI
333      * @param execution
334      * @param aaiObjectName
335      * @param instanceId
336      * @return AAIResultWrapper
337      */
338     private AAIResultWrapper queryAAI(DelegateExecution execution, AAIObjectName aaiObjectName, String instanceId, String errorMsg)
339     {
340         LOGGER.trace(" *****${PREFIX} Start queryAAI *****")
341         String globalSubscriberId = execution.getVariable("globalSubscriberId")
342         String serviceType = execution.getVariable("serviceType")
343
344         org.onap.aaiclient.client.generated.fluentbuilders.ServiceInstance serviceInstanceType = AAIFluentTypeBuilder.business().customer(globalSubscriberId).serviceSubscription(serviceType).serviceInstance(instanceId)
345         def type
346         if (aaiObjectName == Types.ALLOTTED_RESOURCES) {
347             type = serviceInstanceType.allottedResources()
348         } else if (aaiObjectName == Types.SLICE_PROFILES) {
349             type = serviceInstanceType.sliceProfiles()
350         } else {
351             type = serviceInstanceType
352         }
353         def uri = AAIUriFactory.createResourceUri(type)
354         if (!getAAIClient().exists(uri)) {
355             exceptionUtil.buildAndThrowWorkflowException(execution, 2500, errorMsg)
356         }
357         AAIResultWrapper wrapper = getAAIClient().get(uri, NotFoundException.class)
358         LOGGER.trace(" *****${PREFIX} Exit queryAAI *****")
359         return wrapper
360     }
361
362     void terminateNSIQuery(DelegateExecution execution)
363     {
364         logger.debug("Start terminateNSIQuery")
365         
366         String requestId = execution.getVariable("msoRequestId")
367         String nxlId = currentNSSI['nsiServiceInstanceId']
368         String nxlType = "NSI"
369         String messageType = "nsiTerminationResponse"
370         String serviceInstanceId = execution.getVariable("serviceInstanceId")
371         
372         def authHeader = ""
373         String basicAuth = UrnPropertiesReader.getVariable("mso.oof.auth", execution)
374         String msokey = UrnPropertiesReader.getVariable("mso.msoKey", execution)
375
376         String basicAuthValue = utils.encrypt(basicAuth, msokey)
377         if (basicAuthValue != null) {
378             logger.debug( "Obtained BasicAuth username and password for OOF: " + basicAuthValue)
379             try {
380                 authHeader = utils.getBasicAuth(basicAuthValue, msokey)
381                 execution.setVariable("BasicAuthHeaderValue", authHeader)
382             } catch (Exception ex) {
383                 logger.debug( "Unable to encode username and password string: " + ex)
384                 exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - Unable to " +
385                         "encode username and password string")
386             }
387         } else {
388             logger.debug( "Unable to obtain BasicAuth - BasicAuth value null")
389             exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - BasicAuth " +
390                     "value null")
391         }
392
393         URL requestUrl = new URL(oofUrl + "/api/oof/terminate/nxi/v1")
394         String oofRequest = oofUtils.buildTerminateNxiRequest(requestId, nxlId, nxlType, messageType, serviceInstanceId)
395         HttpClient httpClient = new HttpClientFactory().newJsonClient(requestUrl, ONAPComponents.OOF)
396         httpClient.addAdditionalHeader("Authorization", authHeader)
397         Response httpResponse = httpClient.post(oofRequest)
398
399         int responseCode = httpResponse.getStatus()
400         logger.debug("OOF sync response code is: " + responseCode)
401
402         if(responseCode != 200){
403             exceptionUtil.buildAndThrowWorkflowException(execution, responseCode, "Received a Bad Sync Response from OOF.")
404         }       
405         try {
406             Map<String, String> resMap = httpResponse.readEntity(Map.class)
407             boolean terminateResponse = resMap.get("terminateResponse")
408             execution.setVariable("terminateNSI", terminateResponse)
409         } catch (Exception ex) {
410             logger.debug( "Failed to get terminate Response suggested by OOF.")
411             exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Failed to get terminate Response suggested by OOF.")
412         }
413         logger.debug("Finish terminateNSIQuery")
414     }
415 }