From c3826c443cb18822b4fcddd46fbf8cc86f9d9200 Mon Sep 17 00:00:00 2001
From: Christos Tranoris <tranoris@ece.upatras.gr>
Date: Fri, 6 Dec 2024 10:31:09 +0200
Subject: [PATCH] fixes for generic controller support

---
 .../management/CROrchestrationService.java    |  21 +-
 .../management/GCOrchestrationService.java    |  81 +++----
 .../osom/management/ServiceOrderManager.java  |   6 +-
 .../AutomaticallyHandleAction.java            | 204 +++++++++++++++++-
 4 files changed, 264 insertions(+), 48 deletions(-)

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 235012d..cff7c1e 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/GCOrchestrationService.java b/src/main/java/org/etsi/osl/osom/management/GCOrchestrationService.java
index 5b041a6..a7e0dea 100644
--- a/src/main/java/org/etsi/osl/osom/management/GCOrchestrationService.java
+++ b/src/main/java/org/etsi/osl/osom/management/GCOrchestrationService.java
@@ -68,10 +68,10 @@ public class GCOrchestrationService implements JavaDelegate {
 
   public void execute(DelegateExecution execution) {
 
-    logger.info("Ceneric Controller OrchestrationService");
-    logger.info("VariableNames:" + execution.getVariableNames().toString());
-    logger.info("orderid:" + execution.getVariable("orderid").toString());
-    logger.info("contextServiceId:" + execution.getVariable("contextServiceId").toString());
+    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 {
       
@@ -108,36 +108,42 @@ public class GCOrchestrationService implements JavaDelegate {
         ResourceSpecification rspec = serviceOrderManager.retrieveResourceSpec(rSpecRef.getId());
         
         //we will create a resource based on the values of resourcepsecificationRef
-        Resource resourceCR = createRelatedResource( rspec, sorder, aService );
+        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( resourceCR.getId() );
-        rr.setName( resourceCR.getName());
-        rr.setType( resourceCR.getType());
+        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, resourceCR, rspec, sorder.getId(), sorder.getStartDate(),
-              sorder.getExpectedCompletionDate() );
+        response = createNewResourceDeploymentRequest(aService, resourceI, resourceCreate,  sorder.getId() );
         
                 
         
-        if ( response!=null  ) {
-          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);
-        } else {
+        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);
         }
-        Service supd = serviceOrderManager.updateService(aService.getId(), su, false);
         
         return;
 
@@ -187,7 +193,7 @@ public class GCOrchestrationService implements JavaDelegate {
    * @param aService
    * @return
    */
-  private Resource createRelatedResource(ResourceSpecification rspec, ServiceOrder sOrder, Service aService) {
+  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
@@ -221,9 +227,9 @@ public class GCOrchestrationService implements JavaDelegate {
     }
     
     //copy to resource the rest of the characteristics that do not exists yet from the above search
-    copyRemainingSpecCharacteristicsToResourceCharacteristic(rspec , resCreate.getResourceCharacteristic() );     
+    resCreate = copyRemainingSpecCharacteristicsToResourceCharacteristic(rspec , resCreate );     
     
-    return serviceOrderManager.createResource( resCreate, sOrder, rspec.getId() );
+    return resCreate;
 
     
     
@@ -253,8 +259,11 @@ public class GCOrchestrationService implements JavaDelegate {
    * @param spec
    * @param list
    */
-  private void copyRemainingSpecCharacteristicsToResourceCharacteristic(ResourceSpecification spec,
-      @Valid List<org.etsi.osl.tmf.ri639.model.Characteristic> list) {
+  private ResourceCreate copyRemainingSpecCharacteristicsToResourceCharacteristic(ResourceSpecification spec,
+      @Valid ResourceCreate resCreate) {
+    
+    List<org.etsi.osl.tmf.ri639.model.Characteristic> list = resCreate.getResourceCharacteristic();
+    
     for (ResourceSpecificationCharacteristic sourceCharacteristic : spec.getResourceSpecCharacteristic()) {
         if (  sourceCharacteristic.getValueType() != null ) {
             boolean charfound = false;
@@ -321,6 +330,8 @@ public class GCOrchestrationService implements JavaDelegate {
         
     }
     
+    return resCreate;
+    
   }
 
 
@@ -338,33 +349,29 @@ public class GCOrchestrationService implements JavaDelegate {
    * <br>
    * 
    * @param aService reference to the service that the resource and the CR belongs to
-   * @param aResource reference the equivalent resource in TMF repo of the target CR. One to one mapping
+   * @param resourceI reference the equivalent resource in TMF repo of the target CR. One to one mapping
    * @param orderId related service order ID
-   * @param startDate start date of the deployment  (not used currently)
-   * @param endDate end date of the deployment (not used currently)
    * @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 aResource, 
-      ResourceSpecification rRef, 
-      String orderId,
-      OffsetDateTime startDate,
-      OffsetDateTime endDate) {
+  private Resource createNewResourceDeploymentRequest( Service aService, Resource resourceI,
+      ResourceCreate aResourceCreate, 
+      String orderId) {
 
     try {
       Map<String, Object> map = new HashMap<>();
       map.put("org.etsi.osl.serviceId", aService.getId() );
-      map.put("org.etsi.osl.resourceId", aResource.getId() );
-      map.put("org.etsi.osl.prefixName", "gr" + aResource.getId().substring(0, 8) );
+      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/"+aResource.getCategory() + "/" + rRef.getVersion() ;
-      Resource response  = serviceOrderManager.gcGenericResourceDeploymentRequest(queueName , map, aResource);
+      String queueName = "jms:queue:CREATE/"+ aResourceCreate.getCategory() + "/" + aResourceCreate.getResourceVersion() ;
+      Resource response  = serviceOrderManager.gcGenericResourceDeploymentRequest(queueName , map, aResourceCreate);
       
 
       return response;
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 336e487..4d79409 100644
--- a/src/main/java/org/etsi/osl/osom/management/ServiceOrderManager.java
+++ b/src/main/java/org/etsi/osl/osom/management/ServiceOrderManager.java
@@ -42,6 +42,7 @@ 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;
@@ -1086,7 +1087,7 @@ public class ServiceOrderManager {
     
   }
 
-  public Resource gcGenericResourceDeploymentRequest(String queueName, Map<String, Object> map, Resource aResource) {
+  public Resource gcGenericResourceDeploymentRequest(String queueName, Map<String, Object> map, ResourceUpdate aResource) {
     try {
 
       logger.debug("gcGenericResourceDeploymentRequest queueName=" + queueName);
@@ -1110,6 +1111,9 @@ public class ServiceOrderManager {
     return null;
   }
   
+  
+
+  
   /**
    * get  service spec by id from model via bus
    * @param id
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 6bc7ce4..9b9d3b7 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,9 @@ public class AutomaticallyHandleAction  implements JavaDelegate {
     
 	public void execute(DelegateExecution execution) {
 		
-		logger.info("AutomaticallyHandleAction:" + execution.getVariableNames().toString() );
+		logger.debug("AutomaticallyHandleAction:" + execution.getVariableNames().toString() );
+	    logger.debug("Ceneric Controller OrchestrationService");
+	    logger.debug("VariableNames:" + execution.getVariableNames().toString());
 		
 		
 		ObjectMapper mapper = new ObjectMapper();
@@ -42,12 +63,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<ServiceOrderRef> 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 +154,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<Feature> set = source.getActivationFeature();
+      if ( set != null ) {
+          resourceUpdate.setActivationFeature( new ArrayList<Feature>( set ) );
+      }
+      resourceUpdate.setAdministrativeState( source.getAdministrativeState() );
+      Set<AttachmentRefOrValue> set1 = source.getAttachment();
+      if ( set1 != null ) {
+          resourceUpdate.setAttachment( new ArrayList<AttachmentRefOrValue>( set1 ) );
+      }
+      Set<Note> set2 = source.getNote();
+      if ( set2 != null ) {
+          resourceUpdate.setNote( new ArrayList<Note>( set2 ) );
+      }
+      resourceUpdate.setOperationalState( source.getOperationalState() );
+      resourceUpdate.setPlace( source.getPlace() );
+      Set<RelatedParty> set3 = source.getRelatedParty();
+      if ( set3 != null ) {
+          resourceUpdate.setRelatedParty( new ArrayList<RelatedParty>( set3 ) );
+      }
+      @Valid Set<org.etsi.osl.tmf.ri639.model.Characteristic> set4 = source.getResourceCharacteristic();
+      if ( set4 != null ) {
+          resourceUpdate.setResourceCharacteristic( new ArrayList<org.etsi.osl.tmf.ri639.model.Characteristic>( set4 ) );
+      }
+      Set<ResourceRelationship> set5 = source.getResourceRelationship();
+      if ( set5 != null ) {
+          resourceUpdate.setResourceRelationship( new ArrayList<ResourceRelationship>( 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<String, Object> 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<String, Object> 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;
+
+    }
 
 }
-- 
GitLab