diff --git a/src/main/java/org/etsi/osl/osom/management/AutomationCheck.java b/src/main/java/org/etsi/osl/osom/management/AutomationCheck.java index d8aef5d75a29dd9ea47ed4ce1dbe2387f9579b1e..e55f373090fcbafedcd507391daf4f1540654c2e 100644 --- a/src/main/java/org/etsi/osl/osom/management/AutomationCheck.java +++ b/src/main/java/org/etsi/osl/osom/management/AutomationCheck.java @@ -89,7 +89,9 @@ public class AutomationCheck implements JavaDelegate { execution.setVariable("brokeActivity", "RFS_OSM" ); } else if ( spec.getType().equals("ResourceFacingServiceSpecification") && ( spec.findSpecCharacteristicByName( "_CR_SPEC" ) != null ) ) { execution.setVariable("brokeActivity", "RFS_CRSPEC" ); - } + } else if ( spec.getType().equals("ResourceFacingServiceSpecification") ) { + execution.setVariable("brokeActivity", "GRSPEC" ); + } } diff --git a/src/main/java/org/etsi/osl/osom/management/CROrchestrationService.java b/src/main/java/org/etsi/osl/osom/management/CROrchestrationService.java index 235012d76826f393907031bf5c2cf94a126f7f52..cff7c1eecd2da2634ea91d7e724d3d723cf95a9e 100644 --- a/src/main/java/org/etsi/osl/osom/management/CROrchestrationService.java +++ b/src/main/java/org/etsi/osl/osom/management/CROrchestrationService.java @@ -108,6 +108,15 @@ public class CROrchestrationService implements JavaDelegate { rr.setName( resourceCR.getName()); rr.setType( resourceCR.getType()); su.addSupportingResourceItem( rr ); + su.setState(ServiceStateType.RESERVED); + Note successNoteItem = new Note(); + successNoteItem.setText(String.format("Requesting CRIDGE to deploy crspec")); + successNoteItem.setDate(OffsetDateTime.now(ZoneOffset.UTC).toString()); + successNoteItem.setAuthor(compname); + su.addNoteItem(successNoteItem); + Service supd = serviceOrderManager.updateService(aService.getId(), su, false); + + String response = null; if (crspec != null) { @@ -120,22 +129,16 @@ public class CROrchestrationService implements JavaDelegate { servicecrspecLast.getValue().setValue( crspec ); su.addServiceCharacteristicItem(servicecrspecLast); - if ( response!=null && response.equals("OK")) { - su.setState(ServiceStateType.RESERVED); - Note successNoteItem = new Note(); - successNoteItem.setText(String.format("Requesting CRIDGE to deploy crspec")); - successNoteItem.setDate(OffsetDateTime.now(ZoneOffset.UTC).toString()); - successNoteItem.setAuthor(compname); - su.addNoteItem(successNoteItem); - } else { + if ( response==null || !response.equals("OK")) { + su = new ServiceUpdate(); su.setState(ServiceStateType.TERMINATED); Note errNoteItem = new Note(); errNoteItem.setText(String.format("Requesting CRIDGE to deploy crspec failed with message: " + response)); errNoteItem.setDate(OffsetDateTime.now(ZoneOffset.UTC).toString()); errNoteItem.setAuthor(compname); su.addNoteItem(errNoteItem); + supd = serviceOrderManager.updateService(aService.getId(), su, false); } - Service supd = serviceOrderManager.updateService(aService.getId(), su, false); return; diff --git a/src/main/java/org/etsi/osl/osom/management/GCOrchestrationCheckDeploymentService.java b/src/main/java/org/etsi/osl/osom/management/GCOrchestrationCheckDeploymentService.java new file mode 100644 index 0000000000000000000000000000000000000000..7f8d9a47a14e2b0332761264cc404940a7152e46 --- /dev/null +++ b/src/main/java/org/etsi/osl/osom/management/GCOrchestrationCheckDeploymentService.java @@ -0,0 +1,130 @@ +/*- + * ========================LICENSE_START================================= + * org.etsi.osl.osom + * %% + * Copyright (C) 2019 openslice.io + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package org.etsi.osl.osom.management; + +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.ArrayList; +import java.util.List; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.etsi.osl.tmf.common.model.service.Note; +import org.etsi.osl.tmf.common.model.service.ResourceRef; +import org.etsi.osl.tmf.common.model.service.ServiceStateType; +import org.etsi.osl.tmf.ri639.model.Resource; +import org.etsi.osl.tmf.sim638.model.Service; +import org.etsi.osl.tmf.sim638.model.ServiceUpdate; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import jakarta.validation.Valid; + + +@Component(value = "gcOrchestrationCheckDeploymentService") //bean name +public class GCOrchestrationCheckDeploymentService implements JavaDelegate { + + private static final transient Log logger = LogFactory.getLog(GCOrchestrationCheckDeploymentService.class.getName()); + + + + @Value("${spring.application.name}") + private String compname; + + @Autowired + private ServiceOrderManager serviceOrderManager; + + public void execute(DelegateExecution execution) { + + logger.info( "CROrchestrationCheckDeploymentService" ); + logger.info( execution.getVariableNames().toString() ); + + + if ( execution.getVariable("contextServiceId") == null) { + + logger.error( "Variable contextServiceId is NULL!" ); + execution.setVariable("serviceDeploymentFinished", Boolean.TRUE ); + return; + } + Service aService = serviceOrderManager.retrieveService( (String) execution.getVariable("contextServiceId") ); + + if ( aService == null ) { + logger.info( "aService is null for contextServiceId = " +(String) execution.getVariable("contextServiceId") ); + execution.setVariable("serviceDeploymentFinished", Boolean.TRUE ); + return; + } + + execution.setVariable("serviceDeploymentFinished", Boolean.FALSE ); + + ServiceUpdate supd = new ServiceUpdate(); + boolean propagateToSO = false; + + //retrieve the related supporting resource by id and check its status + //ResourceRef supresourceRef = aService.getSupportingResource().stream().findFirst().get();//we assume for now we have only one related resource + + List rlist = new ArrayList(); + for (ResourceRef rref : aService.getSupportingResource()) { + Resource res = serviceOrderManager.retrieveResource(rref.getId()); + + if ( res == null ) { + supd.setState( ServiceStateType.TERMINATED); + execution.setVariable("serviceDeploymentFinished", Boolean.TRUE); + Service serviceResult = serviceOrderManager.updateService( aService.getId(), supd, propagateToSO ); + return; + } + rlist.add(res); + + } + @Valid + ServiceStateType currentState = aService.getState(); + + ServiceStateType nextState = aService.findNextStateBasedOnSupportingResources(rlist); + + if (!currentState.equals(nextState)) { + supd.setState( nextState ); + Note n = new Note(); + n.setText("Service Status Changed to: " + nextState); + n.setAuthor(compname); + n.setDate(OffsetDateTime.now(ZoneOffset.UTC).toString()); + supd.addNoteItem(n); + aService = serviceOrderManager.updateService( aService.getId(), supd, propagateToSO ); + } + + if ( aService!= null ) { + if ( aService.getState().equals(ServiceStateType.ACTIVE) + || aService.getState().equals(ServiceStateType.TERMINATED)) { + + logger.info("Deployment Status OK. Service state = " + aService.getState() ); + execution.setVariable("serviceDeploymentFinished", Boolean.TRUE); + return; + } + } + logger.info("Wait For Deployment Status. "); + + + + + + } + + + +} diff --git a/src/main/java/org/etsi/osl/osom/management/GCOrchestrationService.java b/src/main/java/org/etsi/osl/osom/management/GCOrchestrationService.java new file mode 100644 index 0000000000000000000000000000000000000000..a7e0deadfae41bb956259e83d40bea8bce299b9e --- /dev/null +++ b/src/main/java/org/etsi/osl/osom/management/GCOrchestrationService.java @@ -0,0 +1,397 @@ +/*- + * ========================LICENSE_START================================= + * org.etsi.osl.osom + * %% + * Copyright (C) 2019 openslice.io + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package org.etsi.osl.osom.management; + +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.etsi.osl.tmf.common.model.Any; +import org.etsi.osl.tmf.common.model.EValueType; +import org.etsi.osl.tmf.common.model.service.Characteristic; +import org.etsi.osl.tmf.common.model.service.Note; +import org.etsi.osl.tmf.common.model.service.ResourceRef; +import org.etsi.osl.tmf.common.model.service.ServiceStateType; +import org.etsi.osl.tmf.rcm634.model.ResourceSpecification; +import org.etsi.osl.tmf.rcm634.model.ResourceSpecificationCharacteristic; +import org.etsi.osl.tmf.rcm634.model.ResourceSpecificationCharacteristicValue; +import org.etsi.osl.tmf.rcm634.model.ResourceSpecificationRef; +import org.etsi.osl.tmf.ri639.model.Resource; +import org.etsi.osl.tmf.ri639.model.ResourceCreate; +import org.etsi.osl.tmf.scm633.model.ServiceSpecCharacteristic; +import org.etsi.osl.tmf.scm633.model.ServiceSpecification; +import org.etsi.osl.tmf.sim638.model.Service; +import org.etsi.osl.tmf.sim638.model.ServiceUpdate; +import org.etsi.osl.tmf.so641.model.ServiceOrder; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import jakarta.validation.Valid; + + +@Component(value = "gcOrchestrationService") // bean name +public class GCOrchestrationService implements JavaDelegate { + + private static final transient Log logger = + LogFactory.getLog(GCOrchestrationService.class.getName()); + + + @Value("${spring.application.name}") + private String compname; + + + @Autowired + private ServiceOrderManager serviceOrderManager; + + + public void execute(DelegateExecution execution) { + + logger.debug("Ceneric Controller OrchestrationService"); + logger.debug("VariableNames:" + execution.getVariableNames().toString()); + logger.debug("orderid:" + execution.getVariable("orderid").toString()); + logger.debug("contextServiceId:" + execution.getVariable("contextServiceId").toString()); + + try { + + + ServiceUpdate su = new ServiceUpdate();// the object to update the service + Note noteItem = new Note(); + noteItem.setText(""); + + if (execution.getVariable("contextServiceId") instanceof String contextServiceId) { + + + + ServiceOrder sorder = + serviceOrderManager.retrieveServiceOrder(execution.getVariable("orderid").toString()); + Service aService = + serviceOrderManager.retrieveService( contextServiceId ); + logger.info("Service name:" + aService.getName()); + logger.info("Service state:" + aService.getState()); + logger.info("Request for a Custom Resource creation for Service: " + aService.getId()); + + // we need to retrieve here the Service Spec of this service + + ServiceSpecification spec = + serviceOrderManager.retrieveServiceSpec(aService.getServiceSpecificationRef().getId()); + + if (spec != null) { + + + + + //we need to get the equivalent resource spec. since ServiceSpec is an RFS + ResourceSpecificationRef rSpecRef = spec.getResourceSpecification().stream().findFirst().get(); + + ResourceSpecification rspec = serviceOrderManager.retrieveResourceSpec(rSpecRef.getId()); + + //we will create a resource based on the values of resourcepsecificationRef + ResourceCreate resourceCreate = createRelatedResource( rspec, sorder, aService ); + + + //save it to TMF API service inventory + Resource resourceI = serviceOrderManager.createResource( resourceCreate, sorder, rspec.getId() ); + + + ResourceRef rr = new ResourceRef(); + rr.setId( resourceI.getId() ); + rr.setName( resourceI.getName()); + rr.setType( resourceI.getType()); + su.addSupportingResourceItem( rr ); + + su.setState(ServiceStateType.RESERVED); + Note successNoteItem = new Note(); + successNoteItem.setText(String.format("Requesting Controller of "+ rSpecRef.getName() +" to deploy resource")); + successNoteItem.setDate(OffsetDateTime.now(ZoneOffset.UTC).toString()); + successNoteItem.setAuthor(compname); + su.addNoteItem(successNoteItem); + Service supd = serviceOrderManager.updateService(aService.getId(), su, false); + + Resource response = null; + + response = createNewResourceDeploymentRequest(aService, resourceI, resourceCreate, sorder.getId() ); + + + + if ( response==null ) { + su.setState(ServiceStateType.TERMINATED); + Note errNoteItem = new Note(); + errNoteItem.setText(String.format("Requesting Controller to deploy resource failed ")); + errNoteItem.setDate(OffsetDateTime.now(ZoneOffset.UTC).toString()); + errNoteItem.setAuthor(compname); + su.addNoteItem(errNoteItem); + supd = serviceOrderManager.updateService(aService.getId(), su, false); + } + + return; + + } else { + + logger.error("Cannot retrieve ServiceSpecification for service :" + + (String) execution.getVariable("contextServiceId")); + } + } else { + logger.error("Cannot retrieve variable contextServiceId"); + } + + // if we get here something is wrong so we need to terminate the service. + + + + }catch (Exception e) { + e.printStackTrace(); + } + + + try { + Note noteItem = new Note(); + noteItem.setText("Request to CR FAILED." + noteItem.getText()); + noteItem.setAuthor(compname); + noteItem.setDate(OffsetDateTime.now(ZoneOffset.UTC).toString()); + ServiceUpdate su = new ServiceUpdate();// the object to update the service + su.addNoteItem(noteItem); + su.setState(ServiceStateType.TERMINATED); + serviceOrderManager.updateService(execution.getVariable("contextServiceId").toString(), su, + false); + }catch (Exception e) { + e.printStackTrace(); + } + + } + + + /** + * + * THe resource has a temporary name. + * later on the name and its characteristics are updated via the generic controller + * + * + * @param rSpecRef + * @param sOrder + * @param aService + * @return + */ + private ResourceCreate createRelatedResource(ResourceSpecification rspec, ServiceOrder sOrder, Service aService) { + + /** + * In future releases, it is better to create some helper function in the TMF model that + * Creates a resource from a resource specification, (or a service from a servic spec). + * There are similar functions in other places, so it is better to move them in one place + */ + ResourceCreate resCreate = new ResourceCreate(); + resCreate.setName( rspec.getName()+"-" + aService.getId() ); + resCreate.setCategory( rspec.getCategory() ); + resCreate.resourceVersion( rspec.getVersion() ); + + resCreate.setStartOperatingDate( aService.getStartDate() ); + resCreate.setEndOperatingDate(aService.getEndDate()); + ResourceSpecificationRef rSpecRefObj = new ResourceSpecificationRef() ; + rSpecRefObj.id(rspec.getId()) + .version(rspec.getVersion()) + .name( rspec.getName()) + .setType(rspec.getType()); + resCreate.setResourceSpecification(rSpecRefObj); + + + for (ResourceSpecificationCharacteristic c : rspec.getResourceSpecCharacteristic()) { + for (Characteristic orderCharacteristic : aService.getServiceCharacteristic() ) { + String specCharacteristicToSearch = c.getName(); + if ( orderCharacteristic.getName().equals( specCharacteristicToSearch )) { //copy only characteristics that are related from the order + + resCreate.addResourceCharacteristicItem( addResourceCharacteristicItem(c, orderCharacteristic) ); + break; + } + } + } + + //copy to resource the rest of the characteristics that do not exists yet from the above search + resCreate = copyRemainingSpecCharacteristicsToResourceCharacteristic(rspec , resCreate ); + + return resCreate; + + + + } + + + private org.etsi.osl.tmf.ri639.model.Characteristic addResourceCharacteristicItem(ResourceSpecificationCharacteristic c, Characteristic orderCharacteristic) { + org.etsi.osl.tmf.ri639.model.Characteristic resCharacteristicItem = new org.etsi.osl.tmf.ri639.model.Characteristic(); + resCharacteristicItem.setName( c.getName() ); + resCharacteristicItem.setValueType( c.getValueType() ); + + Any val = new Any(); + val.setValue( orderCharacteristic.getValue().getValue() ); + val.setAlias( orderCharacteristic.getValue().getAlias() ); + + resCharacteristicItem.setValue( val ); + + return resCharacteristicItem; + } + + + /** + * + * This helper function it is better in future to be moved in the TMF model. + * There is similar in resource order + * + * @param spec + * @param list + */ + private ResourceCreate copyRemainingSpecCharacteristicsToResourceCharacteristic(ResourceSpecification spec, + @Valid ResourceCreate resCreate) { + + List list = resCreate.getResourceCharacteristic(); + + for (ResourceSpecificationCharacteristic sourceCharacteristic : spec.getResourceSpecCharacteristic()) { + if ( sourceCharacteristic.getValueType() != null ) { + boolean charfound = false; + for (org.etsi.osl.tmf.ri639.model.Characteristic destchar : list) { + if ( destchar.getName().equals(sourceCharacteristic.getName())) { + charfound = true; + break; + } + } + + if (!charfound) { + + org.etsi.osl.tmf.ri639.model.Characteristic newChar = new org.etsi.osl.tmf.ri639.model.Characteristic(); + newChar.setName( sourceCharacteristic.getName() ); + newChar.setValueType( sourceCharacteristic.getValueType() ); + + if ( sourceCharacteristic.getValueType() != null && sourceCharacteristic.getValueType().equals( EValueType.ARRAY.getValue() ) || + sourceCharacteristic.getValueType() != null && sourceCharacteristic.getValueType().equals( EValueType.SET.getValue() ) ) { + String valString = ""; + for (ResourceSpecificationCharacteristicValue specchar : sourceCharacteristic.getResourceSpecCharacteristicValue()) { + if ( ( specchar.isIsDefault()!= null) && specchar.isIsDefault() ) { + if ( !valString.equals("")) { + valString = valString + ","; + } + valString = valString + "{\"value\":\"" + specchar.getValue().getValue() + "\",\"alias\":\"" + specchar.getValue().getAlias() + "\"}"; + } + + } + + newChar.setValue( new Any( "[" + valString + "]", "") ); + + + } else { + for (ResourceSpecificationCharacteristicValue specchar : sourceCharacteristic.getResourceSpecCharacteristicValue()) { + if ( ( specchar.isIsDefault()!= null) && specchar.isIsDefault() ) { + newChar.setValue( new Any( + specchar.getValue().getValue(), + specchar.getValue().getAlias()) ); + break; + }else { + if (specchar.isIsDefault()== null){ + + logger.info("specchar is null value: " + sourceCharacteristic.getName() ); + } + } + + } + } + + + if ( newChar.getValue() !=null) { + list.add(newChar ); + } else { + newChar.setValue( new Any( + "", + "") ); + list.add(newChar ); + } + + } + + } + + + } + + return resCreate; + + } + + + /** + * + * This function makes a new deployment resource request for a resource specification. + * The request is performed via the message queue. + * The function sends also some headers that maybe are needed for deployment + * These are the headers + *
+ *
org.etsi.osl.serviceId: This is the related service id that the created resource has a reference + *
org.etsi.osl.resourceId: This is the related resource id that the created CR will wrap and reference. There + *
org.etsi.osl.prefixName: we need to add a short prefix (default is cr) to various places. For example in K8s cannot start with a number + *
org.etsi.osl.serviceOrderId: the related service order id of this deployment request + *
+ * + * @param aService reference to the service that the resource and the CR belongs to + * @param resourceI reference the equivalent resource in TMF repo of the target CR. One to one mapping + * @param orderId related service order ID + * @return a Resource as updated. It might return "OK" if everything is ok. + * "SEE OTHER" if there are multiple CRIDGEs then some other cridge will handle the request for the equivalent cluster. + * Any other response is handled as error + * return Resource object from the controller + */ + private Resource createNewResourceDeploymentRequest( Service aService, Resource resourceI, + ResourceCreate aResourceCreate, + String orderId) { + + try { + Map map = new HashMap<>(); + map.put("org.etsi.osl.serviceId", aService.getId() ); + map.put("org.etsi.osl.resourceId", resourceI.getId() ); + map.put("org.etsi.osl.prefixName", "gr" + resourceI.getId().substring(0, 8) ); + map.put("org.etsi.osl.serviceOrderId", orderId ); + + + logger.debug("createNewResourceDeploymentRequest "); + + String queueName = "jms:queue:CREATE/"+ aResourceCreate.getCategory() + "/" + aResourceCreate.getResourceVersion() ; + Resource response = serviceOrderManager.gcGenericResourceDeploymentRequest(queueName , map, aResourceCreate); + + + return response; + + } catch (Exception e) { + logger.error("cridgeDeploymentRequest failed"); + e.printStackTrace(); + } + + return null; + + } + + + private Object getServiceCharacteristic(Service aService, String val) { + if (aService.getServiceCharacteristicByName( val ) !=null ) { + return aService.getServiceCharacteristicByName( val ).getValue().getValue(); + } + return ""; + } + + +} diff --git a/src/main/java/org/etsi/osl/osom/management/ServiceOrderManager.java b/src/main/java/org/etsi/osl/osom/management/ServiceOrderManager.java index 6290743ba0d1e9f690c0fd62db7134e3f611de1e..4d794094b5595c6a248cb197dd74612c8c5b45ec 100644 --- a/src/main/java/org/etsi/osl/osom/management/ServiceOrderManager.java +++ b/src/main/java/org/etsi/osl/osom/management/ServiceOrderManager.java @@ -36,10 +36,13 @@ import org.etsi.osl.model.nfv.NetworkServiceDescriptor; import org.etsi.osl.model.nfv.ScaleDescriptor; import org.etsi.osl.osom.serviceactions.NSActionRequestPayload; import org.etsi.osl.tmf.pm632.model.Organization; +import org.etsi.osl.tmf.rcm634.model.LogicalResourceSpecification; +import org.etsi.osl.tmf.rcm634.model.ResourceSpecification; import org.etsi.osl.tmf.ri639.model.LogicalResource; import org.etsi.osl.tmf.ri639.model.PhysicalResource; import org.etsi.osl.tmf.ri639.model.Resource; import org.etsi.osl.tmf.ri639.model.ResourceCreate; +import org.etsi.osl.tmf.ri639.model.ResourceUpdate; import org.etsi.osl.tmf.scm633.model.ServiceSpecification; import org.etsi.osl.tmf.sim638.model.ServiceActionQueueItem; import org.etsi.osl.tmf.sim638.model.ServiceCreate; @@ -188,7 +191,9 @@ public class ServiceOrderManager { @Value("${CATALOG_GET_RESOURCE_BY_ID}") private String CATALOG_GET_RESOURCE_BY_ID = ""; - + + @Value("${CATALOG_GET_RESOURCESPEC_BY_ID}") + private String CATALOG_GET_RESOURCESPEC_BY_ID = ""; @Transactional public void processOrder(ServiceOrder serviceOrder) { @@ -1082,6 +1087,61 @@ public class ServiceOrderManager { } + public Resource gcGenericResourceDeploymentRequest(String queueName, Map map, ResourceUpdate aResource) { + try { + + logger.debug("gcGenericResourceDeploymentRequest queueName=" + queueName); + + String req = toJsonString(aResource); + Object response = template.requestBodyAndHeaders( queueName, req , map ); + + + if ( !(response instanceof String)) { + logger.error("gcGenericResourceDeploymentRequest response object is wrong."); + return null; + } + logger.debug("gcGenericResourceDeploymentRequest response is: " + response); + Resource res = toJsonObj( (String)response, LogicalResource.class); + return res; + + }catch (Exception e) { + logger.error("Cannot retrieve gcGenericResourceDeploymentRequest response. " + e.toString()); + e.printStackTrace(); + } + return null; + } + + + + + /** + * get service spec by id from model via bus + * @param id + * @return + * @throws IOException + */ + public ResourceSpecification retrieveResourceSpec(String specid) { + logger.info("will retrieve Resource Specification id=" + specid ); + + try { + Object response = template. + requestBody( CATALOG_GET_RESOURCESPEC_BY_ID, specid); + + if ( !(response instanceof String)) { + logger.error("Resource Specification object is wrong."); + return null; + } + LogicalResourceSpecification sor = toJsonObj( (String)response, LogicalResourceSpecification.class); + //logger.debug("retrieveSpec response is: " + response); + return sor; + + }catch (Exception e) { + logger.error("Cannot retrieve Resource Specification details from catalog. " + e.toString()); + } + return null; + } + + } diff --git a/src/main/java/org/etsi/osl/osom/serviceactions/AutomaticallyHandleAction.java b/src/main/java/org/etsi/osl/osom/serviceactions/AutomaticallyHandleAction.java index 6bc7ce47c582184d1a9e7161655637b1df52461c..2602be868670d9edc9ab2d3551eab2a468768d99 100644 --- a/src/main/java/org/etsi/osl/osom/serviceactions/AutomaticallyHandleAction.java +++ b/src/main/java/org/etsi/osl/osom/serviceactions/AutomaticallyHandleAction.java @@ -2,21 +2,40 @@ package org.etsi.osl.osom.serviceactions; import java.time.OffsetDateTime; import java.time.ZoneOffset; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.etsi.osl.osom.management.ServiceOrderManager; +import org.etsi.osl.tmf.common.model.AttachmentRefOrValue; +import org.etsi.osl.tmf.common.model.service.Characteristic; import org.etsi.osl.tmf.common.model.service.Note; +import org.etsi.osl.tmf.common.model.service.ResourceRef; +import org.etsi.osl.tmf.prm669.model.RelatedParty; +import org.etsi.osl.tmf.ri639.model.Feature; +import org.etsi.osl.tmf.ri639.model.Resource; +import org.etsi.osl.tmf.ri639.model.ResourceCreate; +import org.etsi.osl.tmf.ri639.model.ResourceRelationship; +import org.etsi.osl.tmf.ri639.model.ResourceUpdate; import org.etsi.osl.tmf.sim638.model.Service; +import org.etsi.osl.tmf.sim638.model.ServiceActionQueueAction; import org.etsi.osl.tmf.sim638.model.ServiceActionQueueItem; +import org.etsi.osl.tmf.sim638.model.ServiceOrderRef; import org.etsi.osl.tmf.sim638.model.ServiceUpdate; import org.flowable.engine.delegate.DelegateExecution; import org.flowable.engine.delegate.JavaDelegate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import jakarta.validation.Valid; @Component(value = "AutomaticallyHandleAction") //bean name public class AutomaticallyHandleAction implements JavaDelegate { @@ -31,7 +50,8 @@ public class AutomaticallyHandleAction implements JavaDelegate { public void execute(DelegateExecution execution) { - logger.info("AutomaticallyHandleAction:" + execution.getVariableNames().toString() ); + logger.debug("AutomaticallyHandleAction:" + execution.getVariableNames().toString() ); + logger.debug("VariableNames:" + execution.getVariableNames().toString()); ObjectMapper mapper = new ObjectMapper(); @@ -42,12 +62,85 @@ public class AutomaticallyHandleAction implements JavaDelegate { item = mapper.readValue( execution.getVariable("serviceActionItem").toString(), ServiceActionQueueItem.class); aService = mapper.readValue( execution.getVariable("Service").toString(), Service.class); + if ( aService.getSupportingResource().stream().findFirst().isPresent() ) { //there is a resourceRef + + ResourceRef rr = aService.getSupportingResource().stream().findFirst().get(); + + Resource relatedResource = serviceOrderManager.retrieveResource( rr.getId() ); + + ResourceUpdate aResourceUpdate = resourceToResourceUpdate(relatedResource); + + //pass characteristic values from services to resource + Optional sref = aService.getServiceOrder().stream().findFirst(); + String serviceOrderID=""; + if ( sref.isPresent()) { + serviceOrderID = sref.get().getId(); + } + + Boolean allServiceAndResourceCharacteristicsAreTheSame = true; + Boolean onlyStatusCharacteristicsChanged = true; + for (org.etsi.osl.tmf.ri639.model.Characteristic resCharacteristic : aResourceUpdate.getResourceCharacteristic()) { + Characteristic servChar = aService.getServiceCharacteristicByName( resCharacteristic.getName() ); + if ( servChar !=null) { + //we need to check if the characteristics that changed are only from the resources (e.g. start with status. ) + //if there are only from resources then we will not snd back an update request, otherwise we get into an infinite loop + if ( resCharacteristic.getValue().getValue() != null && + servChar.getValue().getValue() != null && + !resCharacteristic.getValue().getValue().equals( servChar.getValue().getValue() ) ) { + allServiceAndResourceCharacteristicsAreTheSame = false; + if ( !servChar.getValue().getValue().startsWith("status.") ) { + onlyStatusCharacteristicsChanged = false; + } else { + + logger.debug("Only Status Characteristic Changed. Will not update the resource!" ); + } + } + + + resCharacteristic.getValue().setValue( servChar.getValue().getValue() ); + + } + } + + + try{ + + Resource response = null; + + if ( item.getAction().equals( ServiceActionQueueAction.EVALUATE_CHARACTERISTIC_CHANGED ) + || item.getAction().equals( ServiceActionQueueAction.EVALUATE_CHILD_CHARACTERISTIC_CHANGED ) + || item.getAction().equals( ServiceActionQueueAction.EVALUATE_CHARACTERISTIC_CHANGED_MANODAY2 ) ) { + + if ( !onlyStatusCharacteristicsChanged && !allServiceAndResourceCharacteristicsAreTheSame) { + response = createNewResourceDeploymentRequest(aService, + relatedResource, aResourceUpdate, + serviceOrderID ); + + } + } else { + + response = createNewResourceDeleteRequest(aService, + relatedResource, aResourceUpdate, + serviceOrderID ); + } + + + }catch (Exception e) { + e.printStackTrace(); + } + + + } + + + ServiceUpdate supd = new ServiceUpdate(); Note n = new Note(); n.setText("Service Action AutomaticallyHandleAction. Action: " + item.getAction() ); n.setAuthor( compname ); n.setDate( OffsetDateTime.now(ZoneOffset.UTC).toString() ); supd.addNoteItem( n ); + serviceOrderManager.deleteServiceActionQueueItem( item ); serviceOrderManager.updateService( aService.getId() , supd, false); @@ -60,5 +153,113 @@ public class AutomaticallyHandleAction implements JavaDelegate { return; } } + + + private ResourceUpdate resourceToResourceUpdate(Resource source) { + if ( source == null ) { + return null; + } + + ResourceUpdate resourceUpdate = new ResourceUpdate(); + + resourceUpdate.setCategory( source.getCategory() ); + resourceUpdate.setDescription( source.getDescription() ); + resourceUpdate.setEndOperatingDate( source.getEndOperatingDate() ); + resourceUpdate.setName( source.getName() ); + resourceUpdate.setResourceVersion( source.getResourceVersion() ); + resourceUpdate.setStartOperatingDate( source.getStartOperatingDate() ); + Set set = source.getActivationFeature(); + if ( set != null ) { + resourceUpdate.setActivationFeature( new ArrayList( set ) ); + } + resourceUpdate.setAdministrativeState( source.getAdministrativeState() ); + Set set1 = source.getAttachment(); + if ( set1 != null ) { + resourceUpdate.setAttachment( new ArrayList( set1 ) ); + } + Set set2 = source.getNote(); + if ( set2 != null ) { + resourceUpdate.setNote( new ArrayList( set2 ) ); + } + resourceUpdate.setOperationalState( source.getOperationalState() ); + resourceUpdate.setPlace( source.getPlace() ); + Set set3 = source.getRelatedParty(); + if ( set3 != null ) { + resourceUpdate.setRelatedParty( new ArrayList( set3 ) ); + } + @Valid Set set4 = source.getResourceCharacteristic(); + if ( set4 != null ) { + resourceUpdate.setResourceCharacteristic( new ArrayList( set4 ) ); + } + Set set5 = source.getResourceRelationship(); + if ( set5 != null ) { + resourceUpdate.setResourceRelationship( new ArrayList( set5 ) ); + } + resourceUpdate.setResourceSpecification( source.getResourceSpecification() ); + resourceUpdate.setResourceStatus( source.getResourceStatus() ); + resourceUpdate.setUsageState( source.getUsageState() ); + + return resourceUpdate; + } + + private Resource createNewResourceDeploymentRequest( Service aService, + Resource resourceI, + ResourceUpdate aResourceUpdate, + String orderId) { + + try { + Map map = new HashMap<>(); + map.put("org.etsi.osl.serviceId", aService.getId() ); + map.put("org.etsi.osl.resourceId", resourceI.getId() ); + map.put("org.etsi.osl.prefixName", "gr" + resourceI.getId().substring(0, 8) ); + map.put("org.etsi.osl.serviceOrderId", orderId ); + + + logger.debug("createNewResourceDeploymentRequest "); + + String queueName = "jms:queue:UPDATE/"+ aResourceUpdate.getCategory() + "/" + aResourceUpdate.getResourceVersion() ; + Resource response = serviceOrderManager.gcGenericResourceDeploymentRequest(queueName , map, aResourceUpdate); + + + return response; + + } catch (Exception e) { + logger.error("cridgeDeploymentRequest failed"); + e.printStackTrace(); + } + + return null; + + } + + private Resource createNewResourceDeleteRequest( Service aService, + Resource resourceI, + ResourceUpdate aResourceUpdate, + String orderId) { + + try { + Map map = new HashMap<>(); + map.put("org.etsi.osl.serviceId", aService.getId() ); + map.put("org.etsi.osl.resourceId", resourceI.getId() ); + map.put("org.etsi.osl.prefixName", "gr" + resourceI.getId().substring(0, 8) ); + map.put("org.etsi.osl.serviceOrderId", orderId ); + + + logger.debug("createNewResourceDeploymentRequest "); + + String queueName = "jms:queue:DELETE/"+ aResourceUpdate.getCategory() + "/" + aResourceUpdate.getResourceVersion() ; + Resource response = serviceOrderManager.gcGenericResourceDeploymentRequest(queueName , map, aResourceUpdate); + + + return response; + + } catch (Exception e) { + logger.error("cridgeDeploymentRequest failed"); + e.printStackTrace(); + } + + return null; + + } } diff --git a/src/main/resources/GenericResourceController.md b/src/main/resources/GenericResourceController.md new file mode 100644 index 0000000000000000000000000000000000000000..55b4418af999439233e07bcd686f853d816a0316 --- /dev/null +++ b/src/main/resources/GenericResourceController.md @@ -0,0 +1,90 @@ +@startuml + +group Controller Startup [Controller Registration] + + control "ResourceController" as ResourceController + entity "TMFAPI" as TMFAPI + queue MQa + + ResourceController -> MQa: RegisterResourceSpec + MQa -> TMFAPI: RegisterResourceSpec + note left + Register a ResourceSpec with + Name, Category, Version + end note + ResourceController -> MQa: QueueRegister + note left + CREATE// + UPDATE// + DELETE// + end note + + +end + + +group Create RFS [Create RFS and underlying resource] + control "ResourceController" as ResourceController + entity "TMFAPI" as TMFAPI + queue MQa + entity "OSOM" as OSOM + + + TMFAPI -> OSOM: ServiceOrderCreate + + OSOM -> OSOM: ServiceCreateTMF + OSOM->MQa : ServiceCreateMSG + MQa -> TMFAPI: ServiceCreateMSG + activate TMFAPI + return Service + MQa -> OSOM: Service + + OSOM -> OSOM: ResourceCreateTMF + + OSOM->MQa : ResourceCreateMSG + MQa -> TMFAPI: ResourceCreate MSG + activate TMFAPI + return Resource + MQa -> OSOM: Resource + + + OSOM -> OSOM: ResourceDeployment + OSOM -> MQa : CreateGenericResourceMSG + note left + Header contains + more metadata + (ServiceID, ResourceID, OrderID) + end note + MQa -> ResourceController: CreateGenericResourceMSG [CREATE//] + + OSOM -> OSOM: WaitFor resourceStatus + +end + + +group Resource Controller Process[Process underlying resource] + ResourceController -> ResourceController: ProcessRequest + + ResourceController->MQa : ResourceUpdate + MQa -> TMFAPI: ResourceUpdate + activate TMFAPI + return Resource + MQa -> ResourceController: Resource + +end + +group OSOM Check Deployment [Wait for underlying resource] + OSOM -> OSOM: WaitFor resourceStatus + OSOM->MQa: Check GETResource + MQa -> TMFAPI: GETResource + activate TMFAPI + return Resource + MQa -> OSOM: Resource + note left + Check resource Status + (e.g. ACTIVE or RESERVED or ALARM) + end note +end + + +@enduml \ No newline at end of file diff --git a/src/main/resources/processes/GenericControllerDeploymentReq.bpmn b/src/main/resources/processes/GenericControllerDeploymentReq.bpmn new file mode 100644 index 0000000000000000000000000000000000000000..ac06cd088d00f287bd0571384f7c441b62161aa7 --- /dev/null +++ b/src/main/resources/processes/GenericControllerDeploymentReq.bpmn @@ -0,0 +1,79 @@ + + + + + + + + + + + + + PT30S + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/processes/ServiceCreationProcess.bpmn b/src/main/resources/processes/ServiceCreationProcess.bpmn index cce6e034f6554cedf624ec3ba6e2a9df7300dd85..1fb3993f21e4fb1e28c7f3779b071cc325febaa3 100644 --- a/src/main/resources/processes/ServiceCreationProcess.bpmn +++ b/src/main/resources/processes/ServiceCreationProcess.bpmn @@ -80,6 +80,11 @@ + + + + + @@ -140,6 +145,9 @@ + + + @@ -296,6 +304,19 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/java/org/etsi/osl/osom/ProcessOrderIntegrationTest.java b/src/test/java/org/etsi/osl/osom/ProcessOrderIntegrationTest.java index 7ef1c9d633fb72b3140eb9fbb2c7cc46881a8616..34e2d5a2bf8ad9055214de2120c664f3d85448a1 100644 --- a/src/test/java/org/etsi/osl/osom/ProcessOrderIntegrationTest.java +++ b/src/test/java/org/etsi/osl/osom/ProcessOrderIntegrationTest.java @@ -184,7 +184,7 @@ public class ProcessOrderIntegrationTest { assertThat(specCirros.getServiceSpecCharacteristic().size() ).isEqualTo(12); assertThat(sorder.getOrderItem().stream().findFirst().get().getService().getServiceCharacteristic().size() ).isEqualTo(2); - assertThat(repositoryService.createProcessDefinitionQuery().count()).isEqualTo(15); + assertThat(repositoryService.createProcessDefinitionQuery().count()).isEqualTo(16); assertThat(taskService.createTaskQuery().count()).isEqualTo(0); assertThat( scmocked.getRequeestedDescriptor() ).isNull();