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.infrastructure.workflow.tasks;
23 import java.io.IOException;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Collections;
27 import java.util.List;
29 import java.util.Optional;
30 import java.util.UUID;
31 import java.util.regex.Matcher;
32 import java.util.regex.Pattern;
33 import java.util.stream.Collectors;
35 import org.camunda.bpm.engine.delegate.DelegateExecution;
36 import org.javatuples.Pair;
37 import org.onap.aai.domain.yang.GenericVnf;
38 import org.onap.aai.domain.yang.L3Network;
39 import org.onap.aai.domain.yang.ServiceInstance;
40 import org.onap.aai.domain.yang.VolumeGroup;
41 import org.onap.so.bpmn.servicedecomposition.bbobjects.VfModule;
42 import org.onap.so.bpmn.servicedecomposition.entities.BuildingBlock;
43 import org.onap.so.bpmn.servicedecomposition.entities.ExecuteBuildingBlock;
44 import org.onap.so.bpmn.servicedecomposition.entities.WorkflowResourceIds;
45 import org.onap.so.bpmn.servicedecomposition.tasks.BBInputSetup;
46 import org.onap.so.bpmn.servicedecomposition.tasks.BBInputSetupUtils;
47 import org.onap.so.client.exception.ExceptionBuilder;
48 import org.onap.so.db.catalog.beans.CollectionNetworkResourceCustomization;
49 import org.onap.so.db.catalog.beans.CollectionResourceCustomization;
50 import org.onap.so.db.catalog.beans.CollectionResourceInstanceGroupCustomization;
51 import org.onap.so.db.catalog.beans.InstanceGroup;
52 import org.onap.so.db.catalog.beans.NetworkCollectionResourceCustomization;
53 import org.onap.so.db.catalog.beans.VfModuleCustomization;
54 import org.onap.so.db.catalog.beans.macro.NorthBoundRequest;
55 import org.onap.so.db.catalog.beans.macro.OrchestrationFlow;
56 import org.onap.so.db.catalog.client.CatalogDbClient;
57 import org.onap.so.logger.MessageEnum;
58 import org.onap.so.logger.MsoLogger;
59 import org.onap.so.serviceinstancebeans.ModelInfo;
60 import org.onap.so.serviceinstancebeans.ModelType;
61 import org.onap.so.serviceinstancebeans.Networks;
62 import org.onap.so.serviceinstancebeans.RequestDetails;
63 import org.onap.so.serviceinstancebeans.Service;
64 import org.onap.so.serviceinstancebeans.ServiceInstancesRequest;
65 import org.onap.so.serviceinstancebeans.VfModules;
66 import org.onap.so.serviceinstancebeans.Vnfs;
67 import org.springframework.beans.factory.annotation.Autowired;
68 import org.springframework.stereotype.Component;
70 import com.fasterxml.jackson.databind.ObjectMapper;
73 public class WorkflowAction {
75 private static final String G_ORCHESTRATION_FLOW = "gOrchestrationFlow";
76 private static final String G_ACTION = "requestAction";
77 private static final String G_CURRENT_SEQUENCE = "gCurrentSequence";
78 private static final String G_REQUEST_ID = "mso-request-id";
79 private static final String G_BPMN_REQUEST = "bpmnRequest";
80 private static final String G_ALACARTE = "aLaCarte";
81 private static final String G_APIVERSION = "apiVersion";
82 private static final String G_URI = "requestUri";
83 private static final String G_ISTOPLEVELFLOW = "isTopLevelFlow";
84 private static final String VNF_TYPE = "vnfType";
85 private static final String SERVICE = "Service";
86 private static final String VNF = "Vnf";
87 private static final String VFMODULE = "VfModule";
88 private static final String VOLUMEGROUP = "VolumeGroup";
89 private static final String NETWORK = "Network";
90 private static final String NETWORKCOLLECTION = "NetworkCollection";
91 private static final String CONFIGURATION = "Configuration";
92 private static final String ASSIGNINSTANCE = "assignInstance";
93 private static final String CREATEINSTANCE = "createInstance";
94 private static final String USERPARAMSERVICE = "service";
95 private static final String supportedTypes = "vnfs|vfModules|networks|networkCollections|volumeGroups|serviceInstances";
96 private static final MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL, WorkflowAction.class);
99 protected BBInputSetup bbInputSetup;
101 protected BBInputSetupUtils bbInputSetupUtils;
103 private ExceptionBuilder exceptionBuilder;
105 private CatalogDbClient catalogDbClient;
107 public void setBbInputSetupUtils(BBInputSetupUtils bbInputSetupUtils) {
108 this.bbInputSetupUtils = bbInputSetupUtils;
111 public void setBbInputSetup(BBInputSetup bbInputSetup) {
112 this.bbInputSetup = bbInputSetup;
115 public void selectExecutionList(DelegateExecution execution) throws Exception {
116 final String requestAction = (String) execution.getVariable(G_ACTION);
117 final String requestId = (String) execution.getVariable(G_REQUEST_ID);
118 final String bpmnRequest = (String) execution.getVariable(G_BPMN_REQUEST);
119 final boolean aLaCarte = (boolean) execution.getVariable(G_ALACARTE);
120 final String apiVersion = (String) execution.getVariable(G_APIVERSION);
121 final String uri = (String) execution.getVariable(G_URI);
122 final String vnfType = (String) execution.getVariable(VNF_TYPE);
123 List<OrchestrationFlow> orchFlows = (List<OrchestrationFlow>) execution.getVariable(G_ORCHESTRATION_FLOW);
124 List<ExecuteBuildingBlock> flowsToExecute = new ArrayList<>();
125 WorkflowResourceIds workflowResourceIds = populateResourceIdsFromApiHandler(execution);
126 List<Pair<WorkflowType, String>> aaiResourceIds = new ArrayList<>();
127 List<Resource> resourceCounter = new ArrayList<>();
129 execution.setVariable("sentSyncResponse", false);
130 execution.setVariable("homing", false);
131 execution.setVariable("calledHoming", false);
134 ObjectMapper mapper = new ObjectMapper();
135 execution.setVariable(G_ISTOPLEVELFLOW, true);
136 ServiceInstancesRequest sIRequest = mapper.readValue(bpmnRequest, ServiceInstancesRequest.class);
137 RequestDetails requestDetails = sIRequest.getRequestDetails();
138 Resource resource = extractResourceIdAndTypeFromUri(uri);
139 WorkflowType resourceType = resource.getResourceType();
140 String resourceId = "";
141 if (resource.isGenerated()) {
142 resourceId = validateResourceIdInAAI(resource.getResourceId(), resourceType,
143 sIRequest.getRequestDetails().getRequestInfo().getInstanceName(), sIRequest.getRequestDetails(),
144 workflowResourceIds);
146 resourceId = resource.getResourceId();
148 execution.setVariable("resourceId", resourceId);
149 execution.setVariable("resourceType", resourceType);
152 if (orchFlows == null || orchFlows.isEmpty()) {
153 orchFlows = queryNorthBoundRequestCatalogDb(execution, requestAction, resourceType, aLaCarte);
156 ModelInfo modelInfo = sIRequest.getRequestDetails().getModelInfo();
157 if(modelInfo.getModelType().equals(ModelType.service)) {
158 key = modelInfo.getModelVersionId();
160 key = modelInfo.getModelCustomizationId();
162 for (OrchestrationFlow orchFlow : orchFlows) {
163 ExecuteBuildingBlock ebb = buildExecuteBuildingBlock(orchFlow, requestId, key, apiVersion, resourceId,
164 requestAction, aLaCarte, vnfType, workflowResourceIds, requestDetails, false, null);
165 flowsToExecute.add(ebb);
168 boolean foundRelated = false;
169 boolean containsService = false;
170 if (resourceType == WorkflowType.SERVICE && requestAction.equalsIgnoreCase(ASSIGNINSTANCE)) {
171 // SERVICE-MACRO-ASSIGN will always get user params with a
173 if (sIRequest.getRequestDetails().getRequestParameters().getUserParams() != null) {
174 List<Map<String, Object>> userParams = sIRequest.getRequestDetails().getRequestParameters()
176 for (Map<String, Object> params : userParams) {
177 if (params.containsKey(USERPARAMSERVICE)) {
178 containsService = true;
181 if (containsService) {
182 traverseUserParamsService(execution, resourceCounter, sIRequest, requestAction);
185 buildAndThrowException(execution,
186 "Service-Macro-Assign request details must contain user params with a service");
188 } else if (resourceType == WorkflowType.SERVICE
189 && requestAction.equalsIgnoreCase(CREATEINSTANCE)) {
190 // SERVICE-MACRO-CREATE will get user params with a service,
191 // a service with a network, a service with a
192 // networkcollection, OR an empty service.
193 // If user params is just a service or null and macro
194 // queries the SI and finds a VNF, macro fails.
196 if (sIRequest.getRequestDetails().getRequestParameters().getUserParams() != null) {
197 List<Map<String, Object>> userParams = sIRequest.getRequestDetails().getRequestParameters()
199 for (Map<String, Object> params : userParams) {
200 if (params.containsKey(USERPARAMSERVICE)) {
201 containsService = true;
205 if (containsService) {
206 foundRelated = traverseUserParamsService(execution, resourceCounter, sIRequest, requestAction);
209 traverseCatalogDbService(execution, sIRequest, resourceCounter);
211 } else if (resourceType == WorkflowType.SERVICE
212 && (requestAction.equalsIgnoreCase("activateInstance")
213 || requestAction.equalsIgnoreCase("unassignInstance")
214 || requestAction.equalsIgnoreCase("deleteInstance"))) {
215 // SERVICE-MACRO-ACTIVATE, SERVICE-MACRO-UNASSIGN, and
216 // SERVICE-MACRO-DELETE
217 // Will never get user params with service, macro will have
218 // to query the SI in AAI to find related instances.
219 traverseAAIService(execution, resourceCounter, resourceId, aaiResourceIds);
220 } else if (resourceType == WorkflowType.SERVICE
221 && requestAction.equalsIgnoreCase("deactivateInstance")) {
222 resourceCounter.add(new Resource(WorkflowType.SERVICE,"",false));
224 buildAndThrowException(execution, "Current Macro Request is not supported");
227 String foundObjects = "";
228 for(WorkflowType type : WorkflowType.values()){
229 foundObjects = foundObjects + type + " - " + resourceCounter.stream().filter(x -> type.equals(x.getResourceType())).collect(Collectors.toList()).size() + " ";
231 msoLogger.info("Found " + foundObjects);
233 if (orchFlows == null || orchFlows.isEmpty()) {
234 orchFlows = queryNorthBoundRequestCatalogDb(execution, requestAction, resourceType, aLaCarte);
236 flowsToExecute = buildExecuteBuildingBlockList(orchFlows, resourceCounter, requestId, apiVersion, resourceId,
237 resourceType, requestAction, aLaCarte, vnfType, workflowResourceIds, requestDetails);
238 if (!resourceCounter.stream().filter(x -> WorkflowType.NETWORKCOLLECTION == x.getResourceType()).collect(Collectors.toList()).isEmpty()) {
239 msoLogger.info("Sorting for Vlan Tagging");
240 flowsToExecute = sortExecutionPathByObjectForVlanTagging(flowsToExecute, requestAction);
242 if (resourceType == WorkflowType.SERVICE
243 && (requestAction.equals(CREATEINSTANCE) || requestAction.equals(ASSIGNINSTANCE))
244 && !resourceCounter.stream().filter(x -> VNF.equals(x.getResourceType())).collect(Collectors.toList()).isEmpty()) {
245 execution.setVariable("homing", true);
246 execution.setVariable("calledHoming", false);
248 if (resourceType == WorkflowType.SERVICE && (requestAction.equalsIgnoreCase(ASSIGNINSTANCE) || requestAction.equalsIgnoreCase(CREATEINSTANCE))){
249 generateResourceIds(flowsToExecute, resourceCounter);
251 updateResourceIdsFromAAITraversal(flowsToExecute, resourceCounter, aaiResourceIds);
255 if (flowsToExecute.isEmpty()) {
256 throw new IllegalStateException("Macro did not come up with a valid execution path.");
259 msoLogger.info("List of BuildingBlocks to execute:");
260 for (ExecuteBuildingBlock ebb : flowsToExecute) {
261 msoLogger.info(ebb.getBuildingBlock().getBpmnFlowName());
264 execution.setVariable(G_CURRENT_SEQUENCE, 0);
265 execution.setVariable("retryCount", 0);
266 execution.setVariable("flowsToExecute", flowsToExecute);
268 } catch (Exception ex) {
270 buildAndThrowException(execution, "Exception in create execution list " + ex.getMessage(), ex);
274 protected List<Resource> sortVfModulesByBaseFirst(List<Resource> vfModuleResources) {
276 for(Resource resource : vfModuleResources){
277 if(resource.isBaseVfModule()){
278 Collections.swap(vfModuleResources, 0, count);
283 return vfModuleResources;
286 private void updateResourceIdsFromAAITraversal(List<ExecuteBuildingBlock> flowsToExecute,
287 List<Resource> resourceCounter, List<Pair<WorkflowType, String>> aaiResourceIds) {
288 for(Pair<WorkflowType,String> pair : aaiResourceIds){
289 msoLogger.debug(pair.getValue0() + ", " + pair.getValue1());
292 Arrays.stream(WorkflowType.values()).filter(type -> !type.equals(WorkflowType.SERVICE)).forEach(type -> {
293 List<Resource> resources = resourceCounter.stream().filter(x -> type.equals(x.getResourceType())).collect(Collectors.toList());
294 for(int i = 0; i < resources.size(); i++){
295 updateWorkflowResourceIds(flowsToExecute, type, resources.get(i).getResourceId(), retrieveAAIResourceId(aaiResourceIds,type), null);
300 private String retrieveAAIResourceId(List<Pair<WorkflowType, String>> aaiResourceIds, WorkflowType resource){
302 for(int i = 0; i<aaiResourceIds.size();i++){
303 if(aaiResourceIds.get(i).getValue0() == resource){
304 id = aaiResourceIds.get(i).getValue1();
305 aaiResourceIds.remove(i);
311 private void generateResourceIds(List<ExecuteBuildingBlock> flowsToExecute, List<Resource> resourceCounter) {
312 Arrays.stream(WorkflowType.values()).filter(type -> !type.equals(WorkflowType.SERVICE)).forEach(type -> {
313 List<Resource> resources = resourceCounter.stream().filter(x -> type.equals(x.getResourceType())).collect(Collectors.toList());
314 for(int i = 0; i < resources.size(); i++){
315 Resource resource = resourceCounter.stream().filter(x -> type.equals(x.getResourceType()))
316 .collect(Collectors.toList()).get(i);
317 updateWorkflowResourceIds(flowsToExecute, type, resource.getResourceId(), null, resource.getVirtualLinkKey()); }
321 protected void updateWorkflowResourceIds(List<ExecuteBuildingBlock> flowsToExecute, WorkflowType resource, String key, String id, String virtualLinkKey){
322 String resourceId = id;
323 if(resourceId==null){
324 resourceId = UUID.randomUUID().toString();
326 for(ExecuteBuildingBlock ebb : flowsToExecute){
327 if(key != null && key.equalsIgnoreCase(ebb.getBuildingBlock().getKey()) && ebb.getBuildingBlock().getBpmnFlowName().contains(resource.toString())){
328 WorkflowResourceIds workflowResourceIds = new WorkflowResourceIds();
329 if(resource == WorkflowType.VNF){
330 workflowResourceIds.setVnfId(resourceId);
331 }else if(resource == WorkflowType.VFMODULE){
332 workflowResourceIds.setVfModuleId(resourceId);
333 }else if(resource == WorkflowType.VOLUMEGROUP){
334 workflowResourceIds.setVolumeGroupId(resourceId);
335 }else if(resource == WorkflowType.NETWORK){
336 workflowResourceIds.setNetworkId(resourceId);
337 }else if(resource == WorkflowType.NETWORKCOLLECTION){
338 workflowResourceIds.setNetworkCollectionId(resourceId);
340 ebb.setWorkflowResourceIds(workflowResourceIds);
342 if(virtualLinkKey != null && ebb.getBuildingBlock().getIsVirtualLink()
343 && virtualLinkKey.equalsIgnoreCase(ebb.getBuildingBlock().getVirtualLinkKey())) {
344 WorkflowResourceIds workflowResourceIds = new WorkflowResourceIds();
345 workflowResourceIds.setNetworkId(resourceId);
346 ebb.setWorkflowResourceIds(workflowResourceIds);
351 protected CollectionResourceCustomization findCatalogNetworkCollection(DelegateExecution execution, org.onap.so.db.catalog.beans.Service service) {
352 CollectionResourceCustomization networkCollection = null;
354 for(CollectionResourceCustomization collectionCust : service.getCollectionResourceCustomizations()){
355 if(catalogDbClient.getNetworkCollectionResourceCustomizationByID(collectionCust.getModelCustomizationUUID())
356 instanceof NetworkCollectionResourceCustomization) {
357 networkCollection = collectionCust;
363 }else if(count > 1) {
364 buildAndThrowException(execution, "Found multiple Network Collections in the Service model, only one per Service is supported.");
366 return networkCollection;
369 protected void traverseCatalogDbService(DelegateExecution execution, ServiceInstancesRequest sIRequest,
370 List<Resource> resourceCounter) {
371 String modelUUID = sIRequest.getRequestDetails().getModelInfo().getModelVersionId();
372 org.onap.so.db.catalog.beans.Service service = catalogDbClient.getServiceByID(modelUUID);
373 if (service == null) {
374 buildAndThrowException(execution, "Could not find the service model in catalog db.");
376 resourceCounter.add(new Resource(WorkflowType.SERVICE,service.getModelUUID(),false));
377 if (service.getVnfCustomizations() == null || service.getVnfCustomizations().isEmpty()) {
378 List<CollectionResourceCustomization> customizations = service.getCollectionResourceCustomizations();
379 if(customizations.isEmpty()) {
380 msoLogger.debug("No Collections found. CollectionResourceCustomization list is empty.");
382 CollectionResourceCustomization collectionResourceCustomization = findCatalogNetworkCollection(execution, service);
383 if(collectionResourceCustomization!=null){
384 resourceCounter.add(new Resource(WorkflowType.NETWORKCOLLECTION,collectionResourceCustomization.getModelCustomizationUUID(),false));
385 msoLogger.debug("Found a network collection");
386 if(collectionResourceCustomization.getCollectionResource()!=null){
387 if(collectionResourceCustomization.getCollectionResource().getInstanceGroup() != null){
388 String toscaNodeType = collectionResourceCustomization.getCollectionResource().getInstanceGroup().getToscaNodeType();
389 if (toscaNodeType != null && toscaNodeType.contains("NetworkCollection")) {
391 InstanceGroup instanceGroup = collectionResourceCustomization.getCollectionResource().getInstanceGroup();
392 CollectionResourceInstanceGroupCustomization collectionInstCust = null;
393 if(!instanceGroup.getCollectionInstanceGroupCustomizations().isEmpty()) {
394 for(CollectionResourceInstanceGroupCustomization collectionInstanceGroupTemp : instanceGroup.getCollectionInstanceGroupCustomizations()) {
395 if(collectionInstanceGroupTemp.getModelCustomizationUUID().equalsIgnoreCase(collectionResourceCustomization.getModelCustomizationUUID())) {
396 collectionInstCust = collectionInstanceGroupTemp;
400 if(collectionInstCust != null && collectionInstCust.getSubInterfaceNetworkQuantity() != null) {
401 minNetworks = collectionInstCust.getSubInterfaceNetworkQuantity();
404 msoLogger.debug("minNetworks: " + minNetworks);
405 CollectionNetworkResourceCustomization collectionNetworkResourceCust = null;
406 for(CollectionNetworkResourceCustomization collectionNetworkTemp : instanceGroup.getCollectionNetworkResourceCustomizations()) {
407 if(collectionNetworkTemp.getNetworkResourceCustomization().getModelCustomizationUUID().equalsIgnoreCase(collectionResourceCustomization.getModelCustomizationUUID())) {
408 collectionNetworkResourceCust = collectionNetworkTemp;
412 for (int i = 0; i < minNetworks; i++) {
413 if(collectionNetworkResourceCust != null && collectionInstCust != null) {
414 Resource resource = new Resource(WorkflowType.VIRTUAL_LINK,collectionNetworkResourceCust.getModelCustomizationUUID(),false);
415 resource.setVirtualLinkKey(Integer.toString(i));
416 resourceCounter.add(resource);
420 msoLogger.debug("Instance Group tosca node type does not contain NetworkCollection: " + toscaNodeType);
423 msoLogger.debug("No Instance Group found for network collection.");
426 msoLogger.debug("No Network Collection found. collectionResource is null");
429 msoLogger.debug("No Network Collection Customization found");
432 if (resourceCounter.stream().filter(x -> WorkflowType.NETWORKCOLLECTION == x.getResourceType()).collect(Collectors.toList()).isEmpty()) {
433 if (service.getNetworkCustomizations() == null) {
434 msoLogger.debug("No networks were found on this service model");
436 for (int i = 0; i < service.getNetworkCustomizations().size(); i++) {
437 resourceCounter.add(new Resource(WorkflowType.NETWORK,service.getNetworkCustomizations().get(i).getModelCustomizationUUID(),false));
442 buildAndThrowException(execution,
443 "Cannot orchestrate Service-Macro-Create without user params with a vnf. Please update ASDC model for new macro orchestration support or add service_recipe records to route to old macro flows");
448 protected void traverseAAIService(DelegateExecution execution, List<Resource> resourceCounter, String resourceId, List<Pair<WorkflowType, String>> aaiResourceIds) {
450 ServiceInstance serviceInstanceAAI = bbInputSetupUtils.getAAIServiceInstanceById(resourceId);
451 org.onap.so.bpmn.servicedecomposition.bbobjects.ServiceInstance serviceInstanceMSO = bbInputSetup
452 .getExistingServiceInstance(serviceInstanceAAI);
453 resourceCounter.add(new Resource(WorkflowType.SERVICE,serviceInstanceMSO.getServiceInstanceId(),false));
454 if (serviceInstanceMSO.getVnfs() != null) {
455 for (org.onap.so.bpmn.servicedecomposition.bbobjects.GenericVnf vnf : serviceInstanceMSO
457 aaiResourceIds.add(new Pair<WorkflowType, String>(WorkflowType.VNF, vnf.getVnfId()));
458 resourceCounter.add(new Resource(WorkflowType.VNF,vnf.getVnfId(),false));
459 if (vnf.getVfModules() != null) {
460 for (VfModule vfModule : vnf.getVfModules()) {
461 aaiResourceIds.add(new Pair<WorkflowType, String>(WorkflowType.VFMODULE, vfModule.getVfModuleId()));
462 resourceCounter.add(new Resource(WorkflowType.VFMODULE,vfModule.getVfModuleId(),false));
465 if (vnf.getVolumeGroups() != null) {
466 for (org.onap.so.bpmn.servicedecomposition.bbobjects.VolumeGroup volumeGroup : vnf
467 .getVolumeGroups()) {
468 aaiResourceIds.add(new Pair<WorkflowType, String>(WorkflowType.VOLUMEGROUP, volumeGroup.getVolumeGroupId()));
469 resourceCounter.add(new Resource(WorkflowType.VOLUMEGROUP,volumeGroup.getVolumeGroupId(),false));
474 if (serviceInstanceMSO.getNetworks() != null) {
475 for (org.onap.so.bpmn.servicedecomposition.bbobjects.L3Network network : serviceInstanceMSO
477 aaiResourceIds.add(new Pair<WorkflowType, String>(WorkflowType.NETWORK, network.getNetworkId()));
478 resourceCounter.add(new Resource(WorkflowType.NETWORK,network.getNetworkId(),false));
481 if (serviceInstanceMSO.getCollection() != null) {
482 msoLogger.debug("found networkcollection");
483 aaiResourceIds.add(new Pair<WorkflowType, String>(WorkflowType.NETWORKCOLLECTION, serviceInstanceMSO.getCollection().getId()));
484 resourceCounter.add(new Resource(WorkflowType.NETWORKCOLLECTION,serviceInstanceMSO.getCollection().getId(),false));
486 } catch (Exception ex) {
487 buildAndThrowException(execution,
488 "Could not find existing Service Instance or related Instances to execute the request on.");
492 protected boolean traverseUserParamsService(DelegateExecution execution, List<Resource> resourceCounter,
493 ServiceInstancesRequest sIRequest, String requestAction)
495 boolean foundRelated = false;
496 boolean foundVfModuleOrVG = false;
497 if (sIRequest.getRequestDetails().getRequestParameters().getUserParams() != null) {
498 List<Map<String, Object>> userParams = sIRequest.getRequestDetails().getRequestParameters().getUserParams();
499 for (Map<String, Object> params : userParams) {
500 if (params.containsKey(USERPARAMSERVICE)) {
501 ObjectMapper obj = new ObjectMapper();
502 String input = obj.writeValueAsString(params.get(USERPARAMSERVICE));
503 Service validate = obj.readValue(input, Service.class);
504 resourceCounter.add(new Resource(WorkflowType.SERVICE,validate.getModelInfo().getModelVersionId(),false));
505 if (validate.getResources().getVnfs() != null) {
506 for (Vnfs vnf : validate.getResources().getVnfs()) {
507 resourceCounter.add(new Resource(WorkflowType.VNF,vnf.getModelInfo().getModelCustomizationId(),false));
509 if (vnf.getVfModules() != null) {
510 for (VfModules vfModule : vnf.getVfModules()) {
511 VfModuleCustomization vfModuleCustomization = catalogDbClient
512 .getVfModuleCustomizationByModelCuztomizationUUID(
513 vfModule.getModelInfo().getModelCustomizationUuid());
514 if (vfModuleCustomization != null) {
515 if(vfModuleCustomization.getVfModule()!=null && vfModuleCustomization.getVfModule().getVolumeHeatTemplate()!=null &&vfModuleCustomization.getVolumeHeatEnv() != null) {
516 resourceCounter.add(new Resource(WorkflowType.VOLUMEGROUP,vfModuleCustomization.getModelCustomizationUUID(),false));
518 foundVfModuleOrVG = true;
520 if(vfModuleCustomization.getVfModule()!=null && vfModuleCustomization.getVfModule().getModuleHeatTemplate()!=null && vfModuleCustomization.getHeatEnvironment()!=null){
522 foundVfModuleOrVG = true;
523 Resource resource = new Resource(WorkflowType.VFMODULE,vfModuleCustomization.getModelCustomizationUUID(),false);
524 if(vfModuleCustomization.getVfModule().getIsBase()!=null && vfModuleCustomization.getVfModule().getIsBase()){
525 resource.setBaseVfModule(true);
527 resource.setBaseVfModule(false);
529 resourceCounter.add(resource);
531 if(!foundVfModuleOrVG){
532 buildAndThrowException(execution, "Could not determine if vfModule was a vfModule or volume group. Heat template and Heat env are null");
539 if (validate.getResources().getNetworks() != null) {
540 for (Networks network : validate.getResources().getNetworks()) {
541 resourceCounter.add(new Resource(WorkflowType.NETWORK,network.getModelInfo().getModelCustomizationId(),false));
544 if (requestAction.equals(CREATEINSTANCE)) {
545 String networkColCustId = queryCatalogDBforNetworkCollection(execution, sIRequest);
546 if (networkColCustId != null) {
547 resourceCounter.add(new Resource(WorkflowType.NETWORKCOLLECTION,networkColCustId,false));
559 protected String queryCatalogDBforNetworkCollection(DelegateExecution execution, ServiceInstancesRequest sIRequest) {
560 org.onap.so.db.catalog.beans.Service service = catalogDbClient
561 .getServiceByID(sIRequest.getRequestDetails().getModelInfo().getModelVersionId());
562 if (service != null) {
563 CollectionResourceCustomization networkCollection = this.findCatalogNetworkCollection(execution, service);
564 if(networkCollection != null) {
565 return networkCollection.getModelCustomizationUUID();
571 protected WorkflowResourceIds populateResourceIdsFromApiHandler(DelegateExecution execution) {
572 WorkflowResourceIds workflowResourceIds = new WorkflowResourceIds();
573 workflowResourceIds.setServiceInstanceId((String) execution.getVariable("serviceInstanceId"));
574 workflowResourceIds.setNetworkId((String) execution.getVariable("networkId"));
575 workflowResourceIds.setVfModuleId((String) execution.getVariable("vfModuleId"));
576 workflowResourceIds.setVnfId((String) execution.getVariable("vnfId"));
577 workflowResourceIds.setVolumeGroupId((String) execution.getVariable("volumeGroupId"));
578 return workflowResourceIds;
581 protected Resource extractResourceIdAndTypeFromUri(String uri) {
582 Pattern patt = Pattern.compile(
583 "[vV]\\d+.*?(?:(?:/(?<type>" + supportedTypes + ")(?:/(?<id>[^/]+))?)(?:/(?<action>[^/]+))?)?$");
584 Matcher m = patt.matcher(uri);
585 Boolean generated = false;
588 msoLogger.debug("found match on " + uri + ": " + m);
589 String type = m.group("type");
590 String id = m.group("id");
591 String action = m.group("action");
593 throw new IllegalArgumentException("Uri could not be parsed. No type found. " + uri);
595 if (action == null) {
596 if (type.equals("serviceInstances") && (id == null || id.equals("assign"))) {
597 id = UUID.randomUUID().toString();
601 if (action.matches(supportedTypes)) {
602 id = UUID.randomUUID().toString();
607 return new Resource(WorkflowType.fromString(convertTypeFromPlural(type)), id, generated);
609 throw new IllegalArgumentException("Uri could not be parsed: " + uri);
613 protected String validateResourceIdInAAI(String generatedResourceId, WorkflowType type, String instanceName,
614 RequestDetails reqDetails, WorkflowResourceIds workflowResourceIds) throws Exception {
616 if ("SERVICE".equalsIgnoreCase(type.toString())) {
617 String globalCustomerId = reqDetails.getSubscriberInfo().getGlobalSubscriberId();
618 String serviceType = reqDetails.getRequestParameters().getSubscriptionServiceType();
619 if (instanceName != null) {
620 Optional<ServiceInstance> serviceInstanceAAI = bbInputSetupUtils
621 .getAAIServiceInstanceByName(globalCustomerId, serviceType, instanceName);
622 if (serviceInstanceAAI.isPresent()) {
623 return serviceInstanceAAI.get().getServiceInstanceId();
626 } else if ("NETWORK".equalsIgnoreCase(type.toString())) {
627 Optional<L3Network> network = bbInputSetupUtils.getRelatedNetworkByNameFromServiceInstance(
628 workflowResourceIds.getServiceInstanceId(), instanceName);
629 if (network.isPresent()) {
630 return network.get().getNetworkId();
632 } else if ("VNF".equalsIgnoreCase(type.toString())) {
633 Optional<GenericVnf> vnf = bbInputSetupUtils.getRelatedVnfByNameFromServiceInstance(
634 workflowResourceIds.getServiceInstanceId(), instanceName);
635 if (vnf.isPresent()) {
636 return vnf.get().getVnfId();
638 } else if ("VFMODULE".equalsIgnoreCase(type.toString())) {
639 GenericVnf vnf = bbInputSetupUtils.getAAIGenericVnf(workflowResourceIds.getVnfId());
640 if (vnf != null && vnf.getVfModules() != null) {
641 for (org.onap.aai.domain.yang.VfModule vfModule : vnf.getVfModules().getVfModule()) {
642 if (vfModule.getVfModuleName().equalsIgnoreCase(instanceName)) {
643 return vfModule.getVfModuleId();
647 } else if ("VOLUMEGROUP".equalsIgnoreCase(type.toString())) {
648 Optional<VolumeGroup> volumeGroup = bbInputSetupUtils
649 .getRelatedVolumeGroupByNameFromVnf(workflowResourceIds.getVnfId(), instanceName);
650 if (volumeGroup.isPresent()) {
651 return volumeGroup.get().getVolumeGroupId();
653 GenericVnf vnf = bbInputSetupUtils.getAAIGenericVnf(workflowResourceIds.getVnfId());
654 if (vnf != null && vnf.getVfModules() != null) {
655 for (org.onap.aai.domain.yang.VfModule vfModule : vnf.getVfModules().getVfModule()) {
656 Optional<VolumeGroup> volumeGroupFromVfModule = bbInputSetupUtils
657 .getRelatedVolumeGroupByNameFromVfModule(vnf.getVnfId(), vfModule.getVfModuleId(), instanceName);
658 if (volumeGroupFromVfModule.isPresent()) {
659 return volumeGroupFromVfModule.get().getVolumeGroupId();
664 return generatedResourceId;
665 } catch (Exception ex) {
667 throw new IllegalStateException(
668 "WorkflowAction was unable to verify if the instance name already exist in AAI.");
672 protected String convertTypeFromPlural(String type) {
673 if (!type.matches(supportedTypes)) {
676 if (type.equals("serviceInstances")) {
679 return type.substring(0, 1).toUpperCase() + type.substring(1, type.length() - 1);
684 protected List<ExecuteBuildingBlock> sortExecutionPathByObjectForVlanTagging(List<ExecuteBuildingBlock> orchFlows,
685 String requestAction) {
686 List<ExecuteBuildingBlock> sortedOrchFlows = new ArrayList<>();
687 if (requestAction.equals(CREATEINSTANCE)) {
688 for (ExecuteBuildingBlock ebb : orchFlows) {
689 if (ebb.getBuildingBlock().getBpmnFlowName().equals("AssignNetworkBB")) {
690 String key = ebb.getBuildingBlock().getKey();
691 boolean isVirtualLink = ebb.getBuildingBlock().getIsVirtualLink();
692 String virtualLinkKey = ebb.getBuildingBlock().getVirtualLinkKey();
693 sortedOrchFlows.add(ebb);
694 for (ExecuteBuildingBlock ebb2 : orchFlows) {
695 if (!isVirtualLink && ebb2.getBuildingBlock().getBpmnFlowName().equals("CreateNetworkBB")
696 && ebb2.getBuildingBlock().getKey().equalsIgnoreCase(key)) {
697 sortedOrchFlows.add(ebb2);
700 if(isVirtualLink && ebb2.getBuildingBlock().getBpmnFlowName().equals("CreateNetworkBB")
701 && ebb2.getBuildingBlock().getVirtualLinkKey().equalsIgnoreCase(virtualLinkKey)) {
702 sortedOrchFlows.add(ebb2);
706 for (ExecuteBuildingBlock ebb2 : orchFlows) {
707 if (!isVirtualLink && ebb2.getBuildingBlock().getBpmnFlowName().equals("ActivateNetworkBB")
708 && ebb2.getBuildingBlock().getKey().equalsIgnoreCase(key)) {
709 sortedOrchFlows.add(ebb2);
712 if(isVirtualLink && ebb2.getBuildingBlock().getBpmnFlowName().equals("ActivateNetworkBB")
713 && ebb2.getBuildingBlock().getVirtualLinkKey().equalsIgnoreCase(virtualLinkKey)) {
714 sortedOrchFlows.add(ebb2);
718 } else if (ebb.getBuildingBlock().getBpmnFlowName().equals("CreateNetworkBB")
719 || ebb.getBuildingBlock().getBpmnFlowName().equals("ActivateNetworkBB")) {
721 } else if (!ebb.getBuildingBlock().getBpmnFlowName().equals("")) {
722 sortedOrchFlows.add(ebb);
725 } else if (requestAction.equals("deleteInstance")) {
726 for (ExecuteBuildingBlock ebb : orchFlows) {
727 if (ebb.getBuildingBlock().getBpmnFlowName().equals("DeactivateNetworkBB")) {
728 sortedOrchFlows.add(ebb);
729 String key = ebb.getBuildingBlock().getKey();
730 for (ExecuteBuildingBlock ebb2 : orchFlows) {
731 if (ebb2.getBuildingBlock().getBpmnFlowName().equals("DeleteNetworkBB")
732 && ebb2.getBuildingBlock().getKey().equalsIgnoreCase(key)) {
733 sortedOrchFlows.add(ebb2);
737 for (ExecuteBuildingBlock ebb2 : orchFlows) {
738 if (ebb2.getBuildingBlock().getBpmnFlowName().equals("UnassignNetworkBB")
739 && ebb2.getBuildingBlock().getKey().equalsIgnoreCase(key)) {
740 sortedOrchFlows.add(ebb2);
744 } else if (ebb.getBuildingBlock().getBpmnFlowName().equals("DeleteNetworkBB")
745 || ebb.getBuildingBlock().getBpmnFlowName().equals("UnassignNetworkBB")) {
747 } else if (!ebb.getBuildingBlock().getBpmnFlowName().equals("")) {
748 sortedOrchFlows.add(ebb);
752 return sortedOrchFlows;
755 protected List<ExecuteBuildingBlock> buildExecuteBuildingBlockList(List<OrchestrationFlow> orchFlows,
756 List<Resource> resourceCounter, String requestId, String apiVersion, String resourceId, WorkflowType resourceType,
757 String requestAction, boolean aLaCarte, String vnfType,
758 WorkflowResourceIds workflowResourceIds, RequestDetails requestDetails) {
759 List<ExecuteBuildingBlock> flowsToExecute = new ArrayList<>();
760 for (OrchestrationFlow orchFlow : orchFlows) {
761 if (orchFlow.getFlowName().contains(SERVICE)) {
762 for (int i = 0; i < resourceCounter.stream().filter(x -> WorkflowType.SERVICE == x.getResourceType()).collect(Collectors.toList()).size(); i++) {
763 workflowResourceIds.setServiceInstanceId(resourceId);
764 flowsToExecute.add(buildExecuteBuildingBlock(orchFlow, requestId, resourceCounter.stream().filter(x -> WorkflowType.SERVICE == x.getResourceType())
765 .collect(Collectors.toList()).get(i).getResourceId(), apiVersion, resourceId,
766 requestAction, aLaCarte, vnfType, workflowResourceIds, requestDetails, false, null));
768 } else if (orchFlow.getFlowName().contains(VNF)) {
769 for (int i = 0; i < resourceCounter.stream().filter(x -> WorkflowType.VNF == x.getResourceType()).collect(Collectors.toList()).size(); i++) {
770 flowsToExecute.add(buildExecuteBuildingBlock(orchFlow, requestId, resourceCounter.stream().filter(x -> WorkflowType.VNF == x.getResourceType())
771 .collect(Collectors.toList()).get(i).getResourceId(), apiVersion, resourceId,
772 requestAction, aLaCarte, vnfType, workflowResourceIds, requestDetails, false, null));
774 } else if (orchFlow.getFlowName().contains(NETWORK)
775 && !orchFlow.getFlowName().contains(NETWORKCOLLECTION)) {
776 for (int i = 0; i < resourceCounter.stream().filter(x -> WorkflowType.NETWORK == x.getResourceType()).collect(Collectors.toList()).size(); i++) {
777 flowsToExecute.add(buildExecuteBuildingBlock(orchFlow, requestId, resourceCounter.stream().filter(x -> WorkflowType.NETWORK == x.getResourceType())
778 .collect(Collectors.toList()).get(i).getResourceId(), apiVersion, resourceId,
779 requestAction, aLaCarte, vnfType, workflowResourceIds, requestDetails, false, null));
781 for (int i = 0; i < resourceCounter.stream().filter(x -> WorkflowType.VIRTUAL_LINK == x.getResourceType()).collect(Collectors.toList()).size(); i++) {
782 Resource resource = resourceCounter.stream().filter(x -> WorkflowType.VIRTUAL_LINK == x.getResourceType())
783 .collect(Collectors.toList()).get(i);
784 flowsToExecute.add(buildExecuteBuildingBlock(orchFlow, requestId, resource.getResourceId(), apiVersion, resourceId,
785 requestAction, aLaCarte, vnfType, workflowResourceIds, requestDetails, true, resource.getVirtualLinkKey()));
787 } else if (orchFlow.getFlowName().contains(VFMODULE)) {
788 List<Resource> vfModuleResourcesSorted = sortVfModulesByBaseFirst(resourceCounter.stream().filter(x -> WorkflowType.VFMODULE == x.getResourceType())
789 .collect(Collectors.toList()));
790 for (int i = 0; i < vfModuleResourcesSorted.size(); i++) {
791 flowsToExecute.add(buildExecuteBuildingBlock(orchFlow, requestId, vfModuleResourcesSorted.get(i).getResourceId(), apiVersion, resourceId,
792 requestAction, aLaCarte, vnfType, workflowResourceIds, requestDetails, false, null));
794 } else if (orchFlow.getFlowName().contains(VOLUMEGROUP)) {
795 for (int i = 0; i < resourceCounter.stream().filter(x -> WorkflowType.VOLUMEGROUP == x.getResourceType()).collect(Collectors.toList()).size(); i++) {
796 flowsToExecute.add(buildExecuteBuildingBlock(orchFlow, requestId, resourceCounter.stream().filter(x -> WorkflowType.VOLUMEGROUP == x.getResourceType())
797 .collect(Collectors.toList()).get(i).getResourceId(), apiVersion, resourceId,
798 requestAction, aLaCarte, vnfType, workflowResourceIds, requestDetails, false, null));
800 } else if (orchFlow.getFlowName().contains(NETWORKCOLLECTION)) {
801 for (int i = 0; i < resourceCounter.stream().filter(x -> WorkflowType.NETWORKCOLLECTION == x.getResourceType()).collect(Collectors.toList()).size(); i++) {
802 flowsToExecute.add(buildExecuteBuildingBlock(orchFlow, requestId, resourceCounter.stream().filter(x -> WorkflowType.NETWORKCOLLECTION == x.getResourceType())
803 .collect(Collectors.toList()).get(i).getResourceId(), apiVersion, resourceId,
804 requestAction, aLaCarte, vnfType, workflowResourceIds, requestDetails, false, null));
806 } else if (orchFlow.getFlowName().contains(CONFIGURATION)) {
807 for (int i = 0; i < resourceCounter.stream().filter(x -> WorkflowType.CONFIGURATION == x.getResourceType()).collect(Collectors.toList()).size(); i++) {
808 flowsToExecute.add(buildExecuteBuildingBlock(orchFlow, requestId, resourceCounter.stream().filter(x -> WorkflowType.CONFIGURATION == x.getResourceType())
809 .collect(Collectors.toList()).get(i).getResourceId(), apiVersion, resourceId,
810 requestAction, aLaCarte, vnfType, workflowResourceIds, requestDetails, false, null));
813 flowsToExecute.add(buildExecuteBuildingBlock(orchFlow, requestId, "", apiVersion, resourceId,
814 requestAction, aLaCarte, vnfType, workflowResourceIds, requestDetails, false, null));
817 return flowsToExecute;
820 protected ExecuteBuildingBlock buildExecuteBuildingBlock(OrchestrationFlow orchFlow, String requestId, String key,
821 String apiVersion, String resourceId, String requestAction, boolean aLaCarte, String vnfType,
822 WorkflowResourceIds workflowResourceIds, RequestDetails requestDetails, boolean isVirtualLink, String virtualLinkKey) {
823 ExecuteBuildingBlock executeBuildingBlock = new ExecuteBuildingBlock();
824 BuildingBlock buildingBlock = new BuildingBlock();
825 buildingBlock.setBpmnFlowName(orchFlow.getFlowName());
826 buildingBlock.setMsoId(UUID.randomUUID().toString());
827 buildingBlock.setKey(key);
828 buildingBlock.setIsVirtualLink(isVirtualLink);
829 buildingBlock.setVirtualLinkKey(virtualLinkKey);
830 executeBuildingBlock.setApiVersion(apiVersion);
831 executeBuildingBlock.setaLaCarte(aLaCarte);
832 executeBuildingBlock.setRequestAction(requestAction);
833 executeBuildingBlock.setResourceId(resourceId);
834 executeBuildingBlock.setVnfType(vnfType);
835 executeBuildingBlock.setWorkflowResourceIds(workflowResourceIds);
836 executeBuildingBlock.setRequestId(requestId);
837 executeBuildingBlock.setBuildingBlock(buildingBlock);
838 executeBuildingBlock.setRequestDetails(requestDetails);
839 return executeBuildingBlock;
842 protected List<OrchestrationFlow> queryNorthBoundRequestCatalogDb(DelegateExecution execution, String requestAction,
843 WorkflowType resourceName, boolean aLaCarte) {
844 List<OrchestrationFlow> listToExecute = new ArrayList<>();
845 NorthBoundRequest northBoundRequest = catalogDbClient
846 .getNorthBoundRequestByActionAndIsALaCarteAndRequestScope(requestAction, resourceName.toString(), aLaCarte);
847 if(northBoundRequest == null){
849 buildAndThrowException(execution,"The request: ALaCarte " + resourceName + " " + requestAction + " is not supported by GR_API.");
851 buildAndThrowException(execution,"The request: Macro " + resourceName + " " + requestAction + " is not supported by GR_API.");
854 if(northBoundRequest.getIsToplevelflow()!=null){
855 execution.setVariable(G_ISTOPLEVELFLOW, northBoundRequest.getIsToplevelflow());
857 List<OrchestrationFlow> flows = northBoundRequest.getOrchestrationFlowList();
859 flows = new ArrayList<>();
860 for (OrchestrationFlow flow : flows) {
861 if (!flow.getFlowName().contains("BB")) {
862 List<OrchestrationFlow> macroQueryFlows = catalogDbClient
863 .getOrchestrationFlowByAction(flow.getFlowName());
864 for (OrchestrationFlow macroFlow : macroQueryFlows) {
865 listToExecute.add(macroFlow);
868 listToExecute.add(flow);
872 return listToExecute;
875 protected void buildAndThrowException(DelegateExecution execution, String msg, Exception ex) {
876 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(),
877 MsoLogger.ErrorCode.UnknownError, msg, ex);
878 execution.setVariable("WorkflowActionErrorMessage", msg);
879 exceptionBuilder.buildAndThrowWorkflowException(execution, 7000, msg);
882 protected void buildAndThrowException(DelegateExecution execution, String msg) {
883 msoLogger.error(msg);
884 execution.setVariable("WorkflowActionErrorMessage", msg);
885 exceptionBuilder.buildAndThrowWorkflowException(execution, 7000, msg);
888 public void handleRuntimeException (DelegateExecution execution){
889 StringBuffer wfeExpMsg = new StringBuffer("Runtime error ");
890 String runtimeErrorMessage = null;
892 String javaExpMsg = (String) execution.getVariable("BPMN_javaExpMsg");
893 if (javaExpMsg != null && !javaExpMsg.isEmpty()) {
894 wfeExpMsg = wfeExpMsg.append(": ").append(javaExpMsg);
896 runtimeErrorMessage = wfeExpMsg.toString();
897 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, runtimeErrorMessage, "BPMN", MsoLogger.getServiceName(),
898 MsoLogger.ErrorCode.UnknownError, runtimeErrorMessage);
899 execution.setVariable("WorkflowActionErrorMessage", runtimeErrorMessage);
900 } catch (Exception e){
901 //if runtime message was mulformed
902 runtimeErrorMessage = "Runtime error";
904 exceptionBuilder.buildAndThrowWorkflowException(execution, 7000, runtimeErrorMessage);